Javascript - 通过 reduce 方法计算数组元素直到出现特定值不会给出正确的输出
Javascript - Counting array elements by reduce method until specific value occurs doesn't give a correct output
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))
请检查我如何让它工作。犯了一些错误,但不知道到底是什么。输出是一个函数而不是结果。
调用如下:
console.log(sum(arr, 0)());
执行函数需要括号()
sum(arr, 0)
没有括号,您在变量中存储了对函数的引用
由于您需要在数组的中途停止对值求和,这可能最简单地使用 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));
这在 .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))
我们现在正确地进行检查 - 当 x
为零(num
的值)时,num==x
将 return true
。然而,结果是错误的,因为这只是 returns true
once 但任何其他迭代它仍然是 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
to find the first instance of a value and 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/lodash@4.17.15/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/lodash@4.17.15/lodash.min.js"></script>
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))
请检查我如何让它工作。犯了一些错误,但不知道到底是什么。输出是一个函数而不是结果。
调用如下:
console.log(sum(arr, 0)());
执行函数需要括号()
sum(arr, 0)
没有括号,您在变量中存储了对函数的引用
由于您需要在数组的中途停止对值求和,这可能最简单地使用 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));
这在 .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))
我们现在正确地进行检查 - 当 x
为零(num
的值)时,num==x
将 return true
。然而,结果是错误的,因为这只是 returns true
once 但任何其他迭代它仍然是 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
to find the first instance of a value and 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/lodash@4.17.15/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/lodash@4.17.15/lodash.min.js"></script>