JavaScript 数组缩减为子数组的总长度 - 为什么这不起作用?
JavaScript array reduce to sum lengths of sub-arrays - why doesn't this work?
我在 JavaScript 中尝试这个 reduce
时没有得到预期的结果:
let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
x.reduce((a,b) => a.length + b.length, []);
很简单吧?这是我期望发生的事情,一步一步:
----------------------------------------------------------------
| callback | a (accumulator) | b (currentValue) | return value |
----------------------------------------------------------------
| 1st run | 0 | 3 | 3 |
----------------------------------------------------------------
| 2nd run | 3 | 3 | 6 |
----------------------------------------------------------------
| 2nd run | 6 | 3 | 9 |
----------------------------------------------------------------
我实际上得到了什么? NaN
。在英语中,如果我理解正确,迭代器首先查看我给它的初始值(空数组作为 reduce
的第二个参数)并且由参数 a
表示。我的代码在添加的两个参数上显示了一个简单的 .length
。我哪里错了?
.reduce()
API 期望您的回调函数将 return 累加器值(在您的情况下,开始为 []
的值)。您的回调只是 return 一个值。
要使您的代码正常工作,您需要类似以下内容:
x.reduce((a,b) => { a.push(a.length + b.length); return a; }, []);
现在,如果您真正想要的是数组长度的总和,那么无论如何您都不想累加到数组中;你想要一个简单的总和。而不是让累加器是一个数组,那么它只需要是一个数字:
var sum = x.reduce(((sum, array) => sum + array.length), 0);
从零开始,每次调用函数都会将数组长度加到总和中。
上面的 Pointy 代码(实际上 return 9 并不像预期的那样)让我找到了这个可行的解决方案:
let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
x.reduce((a,b) => a + b.length, 0);
Meager 在评论中还指出,这是 map/reduce
组合的经典案例(更简洁的解决方案):
let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
x.map(a => a.length).reduce((a,b) => a + b);
我认为这就是您想要做的(为清楚起见重命名了变量):
let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
x.reduce((acc,element) => acc + element.length, 0);
这是逐步发生的方式:
--------------------------------------------------------------
| callback | acc | element | element.length | return value |
--------------------------------------------------------------
| 1st run | 0 | [1, 2, 3] | 3 | 3 |
--------------------------------------------------------------
| 2nd run | 3 | [4, 5, 6] | 3 | 6 |
--------------------------------------------------------------
| 3rd run | 6 | [7, 8, 9] | 3 | 9 |
--------------------------------------------------------------
作为使用 reduce
的替代方法,展平数组并获取结果的长度。
function flatten(a) { return [].concat(...a); }
const x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
const length = flatten(x).length;
console.log(length);
上面flatten
的实现是针对深度为一或二的数组。 Extend/replace 对于嵌套更深的数组,它是必要的。
我在 JavaScript 中尝试这个 reduce
时没有得到预期的结果:
let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
x.reduce((a,b) => a.length + b.length, []);
很简单吧?这是我期望发生的事情,一步一步:
----------------------------------------------------------------
| callback | a (accumulator) | b (currentValue) | return value |
----------------------------------------------------------------
| 1st run | 0 | 3 | 3 |
----------------------------------------------------------------
| 2nd run | 3 | 3 | 6 |
----------------------------------------------------------------
| 2nd run | 6 | 3 | 9 |
----------------------------------------------------------------
我实际上得到了什么? NaN
。在英语中,如果我理解正确,迭代器首先查看我给它的初始值(空数组作为 reduce
的第二个参数)并且由参数 a
表示。我的代码在添加的两个参数上显示了一个简单的 .length
。我哪里错了?
.reduce()
API 期望您的回调函数将 return 累加器值(在您的情况下,开始为 []
的值)。您的回调只是 return 一个值。
要使您的代码正常工作,您需要类似以下内容:
x.reduce((a,b) => { a.push(a.length + b.length); return a; }, []);
现在,如果您真正想要的是数组长度的总和,那么无论如何您都不想累加到数组中;你想要一个简单的总和。而不是让累加器是一个数组,那么它只需要是一个数字:
var sum = x.reduce(((sum, array) => sum + array.length), 0);
从零开始,每次调用函数都会将数组长度加到总和中。
上面的 Pointy 代码(实际上 return 9 并不像预期的那样)让我找到了这个可行的解决方案:
let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
x.reduce((a,b) => a + b.length, 0);
Meager 在评论中还指出,这是 map/reduce
组合的经典案例(更简洁的解决方案):
let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
x.map(a => a.length).reduce((a,b) => a + b);
我认为这就是您想要做的(为清楚起见重命名了变量):
let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
x.reduce((acc,element) => acc + element.length, 0);
这是逐步发生的方式:
--------------------------------------------------------------
| callback | acc | element | element.length | return value |
--------------------------------------------------------------
| 1st run | 0 | [1, 2, 3] | 3 | 3 |
--------------------------------------------------------------
| 2nd run | 3 | [4, 5, 6] | 3 | 6 |
--------------------------------------------------------------
| 3rd run | 6 | [7, 8, 9] | 3 | 9 |
--------------------------------------------------------------
作为使用 reduce
的替代方法,展平数组并获取结果的长度。
function flatten(a) { return [].concat(...a); }
const x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
const length = flatten(x).length;
console.log(length);
上面flatten
的实现是针对深度为一或二的数组。 Extend/replace 对于嵌套更深的数组,它是必要的。