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 对于嵌套更深的数组,它是必要的。