Javascript - 通过reduce方法计算数组元素,直到出现特定的值,但没有给出正确的输出。

问题描述 投票:0回答:2
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))

请检查一下,我怎么才能让它工作。做错了什么,但不知道具体是什么。输出的是一个函数而不是结果。

javascript arrays reduce
2个回答
1
投票

这是尴尬的做 .reduce 因为它经过 全部 数组。如果我们做一个天真的实现,你可以看到问题。

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))

我们现在要正确地进行检查 num==x 将返回 truex 为零( num). 然而,结果是错误的,因为这只返回了 true 曾经 但任何其他的迭代,它仍然是 true. 而这里也是同样的事情,有更多的日志,描述了过程中的每一步。

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))

所以,你需要添加一些标志,在迭代之间持续存在,所以不会丢失。

其中一个选择是有一个外部标志,你可以在 reduce 回调。

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 回调,并在调用之间传递。最后的工作原理是一样的,但让回调函数变得纯粹。代价是一些非正统的构造。

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 但您可以使用其他方法,那么您可以使用 Array#indexOf 来寻找一个值的第一个实例,并 Array#slice 数组中包含任何值,直到目标值。

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))

或者作为一个链式表达式。

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))

其他库可能有一个 takeUntiltakeWhile 操作,这更接近你的要求--它得到一个数组 苗头 以至于 一个给定的值或条件。然后,你可以减少该结果。

下面是一个使用 Lodash#takeWhile

通过在这里使用链式,Lodash会进行懒惰评估,所以它只会对数组进行一次扫描,而不是扫描一次找到结束索引,然后再次对数组进行求和。

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/[email protected]/lodash.min.js"></script>

作为一个说明,如果你 使用Lodash,那么你也可以使用 _.sum(). 我没有上面的只是为了说明如何通用的 takeUntiltakeWhile 的样子。

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/[email protected]/lodash.min.js"></script>

1
投票

因为你需要在数组的一部分停止求和,所以最简单的方法是使用一个叫做 for 循环。

const arr = [5, 6, 0, 7, 8];
const num = 0;

let sum = 0;
for (let i = 0; i < arr.length; i++) {
  if (arr[i] == num) break;
  sum += arr[i];
}
console.log(sum);

如果你想使用 reduce,你需要保留一面旗帜,上面写着你是否看到了。num 值,这样你就可以停止从数组中添加值。

const arr = [5, 6, 0, 7, 8];

const sum = (arr, num) => {
  let seen = false;
  return arr.reduce((c, v) => {
    if (seen || v == num) {
      seen = true;
      return c;
    }
    return c + v;
  }, 0);
}

console.log(sum(arr, 0));
console.log(sum(arr, 8));

0
投票

调用它的方法如下。

console.log(sum(arr, 0)());

0
投票

你需要用括号来执行这个函数 ()

sum(arr, 0)

没有括号的情况下,我们将函数的引用存储在变量

© www.soinside.com 2019 - 2024. All rights reserved.