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))
请检查一下,我怎么才能让它工作。做错了什么,但不知道具体是什么。输出的是一个函数而不是结果。
这是尴尬的做 .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
将返回 true
当 x
为零( 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))
其他库可能有一个 takeUntil
或 takeWhile
操作,这更接近你的要求--它得到一个数组 从 苗头 以至于 一个给定的值或条件。然后,你可以减少该结果。
下面是一个使用 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()
. 我没有上面的只是为了说明如何通用的 takeUntil
takeWhile
的样子。
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>
因为你需要在数组的一部分停止求和,所以最简单的方法是使用一个叫做 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));
调用它的方法如下。
console.log(sum(arr, 0)());
你需要用括号来执行这个函数 ()
sum(arr, 0)
没有括号的情况下,我们将函数的引用存储在变量