Javascript-通过reduce方法对数组元素进行计数直到出现特定的值不会给出正确的输出 [英] Javascript - Counting array elements by reduce method until specific value occurs doesn't give a correct output

查看:401
本文介绍了Javascript-通过reduce方法对数组元素进行计数直到出现特定的值不会给出正确的输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

const arr = [5,6,0,7,8];
const sum = (arr,num) => arr.reduce((total)=>(num==0 ? total : total+num), 0) 
console.log(sum(arr, 0))

请检查如何使它正常工作.犯了一些错误,但不知道到底是什么.输出是函数而不是结果.

Please check how can I make it work. Did some mistake but don't know what exactly. Output is a function instead of a result.

推荐答案

.reduce 中这样做很尴尬,因为它会通过 entire 数组.如果我们只做一个简单的实现,就可以看到问题所在:

This is awkward to do in .reduce because it goes through the entire array. If we do a naive implementation you can see the problem:

const arr = [5,6,0,7,8];
const sum = (arr,num) => arr.reduce((total, x)=>(num==x ? total : total+x), 0) 
console.log(sum(arr, 0))

我们现在正确进行检查-当 x 为零( num的值)时, num == x 将返回 true ).但是,结果是错误的,因为它只返回 true 一次,但是任何其他迭代仍然是 true .这是具有更多日志记录的同一件事,它描述了过程的每个步骤:

We now make the check correctly - num==x will return true when x is zero (the value of num). However, the result is wrong because this only returns true once but any other iteration it's still true. And here is the same thing with more logging that describes each step of the process:

const arr = [5,6,0,7,8];
const sum = (arr,num) => arr.reduce((total, x)=> {
  const boolCheck = num==x;
  const result = boolCheck ? total : total+x;
  console.log(
`total: ${total}
num: ${num}
x: ${x}
boolCheck: ${boolCheck}
result: ${result}`);

    return result;
  }, 0) 
console.log(sum(arr, 0))

因此,您需要添加一些在两次迭代之间仍然存在的标志,以免丢失.

So, you need to add some flag that persists between iterations, so it doesn't get lost.

一种选择是拥有一个在 reduce 回调中更改的外部标志:

One option is to have an external flag that you change within the reduce callback:

const arr = [5,6,0,7,8];
const sum = (arr,num) => {
  let finished = false;
  return arr.reduce((total, x) => {
    if(x === num)
      finished = true;
      
    return finished ? total : total+x;
  }, 0)
}
console.log(sum(arr, 0))

或者,您可以在 reduce 回调内部使用该标志,并将其在两次调用之间传递.最后,它的工作方式相同,但使回调函数纯净.以一些非传统的构造为代价:

Alternatively, you can have that flag internal to the reduce callback and pass it around between calls. It works the same way in the end but makes the callback function pure. At the cost of some unorthodox construct:

const arr = [5,6,0,7,8];
const sum = (arr,num) => {
  return arr.reduce(({total, finished}, x) => {
    if(x === num)
      finished = true;

    total = finished ? total : total+x;

    return {total, finished};
  }, {total: 0, finished: false})
  .total
}
console.log(sum(arr, 0))

如果您想使用 reduce ,但是可以使用其他方法,则可以使用

If you want to use reduce but you're OK with using other methods, then you can use Array#indexOf to find the first instance of a value and Array#slice the array that contains any value up to the target value:

const arr = [5,6,0,7,8];
const sum = (arr,num) => {
  const endIndex = arr.indexOf(num);
  
  return arr.slice(0, endIndex)
    .reduce((total, x)=> total+x, 0)
}
console.log(sum(arr, 0))

或作为一个链接表达式:

Or in as one chained expression:

const arr = [5,6,0,7,8];
const sum = (arr,num) => arr
  .slice(0, arr.indexOf(num))
  .reduce((total, x)=> total+x, 0);

console.log(sum(arr, 0))

其他库可能具有 takeUntil takeWhile 操作,该操作甚至更接近于您想要的操作-它从一开始就为您提供了一个数组 最多给定值或条件.然后,您可以减少结果.

Other libraries may have a takeUntil or takeWhile operation which is even closer to what you want - it gets you an array from the beginning up to a given value or condition. You can then reduce the result of that.

以下是使用 Lodash#takeWhile

Here is an example of this using Lodash#takeWhile

通过在此处使用链接,Lodash将进行延迟评估,因此它将只遍历数组一次,而不是扫描一次以查找结束索引并再次遍历数组以对其求和.

By using chaining here, Lodash will do lazy evaluation, so it will only go through the array once, instead of scanning once to find the end index and going through the array again to sum it.

const arr = [5,6,0,7,8];
const sum = (arr,num) => _(arr)
  .takeWhile(x => x !== num)
  .reduce((total, x)=>total+x, 0)

console.log(sum(arr, 0))

<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>

请注意,如果您使用Lodash ,那么您也可以使用

As a note, if you are using Lodash, then you may as well use _.sum(). I didn't above just to illustrate how a generic takeUntil/takeWhile looks.

const arr = [5, 6, 0, 7, 8];
const sum = (arr, num) => _(arr)
  .takeWhile(x => x !== num)
  .sum()

console.log(sum(arr, 0))

<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>

这篇关于Javascript-通过reduce方法对数组元素进行计数直到出现特定的值不会给出正确的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆