如何在对象数组上调用 reduce 来求和它们的属性?

假设我想对 中的每个元素求和。a.xarr

arr = [ { x: 1 }, { x: 2 }, { x: 4 } ];
arr.reduce(function(a, b){ return a.x + b.x; }); // => NaN

我有理由相信,这是在某个时候。a.xundefined

以下工作正常

arr = [ 1, 2, 4 ];
arr.reduce(function(a, b){ return a + b; }); // => 7

在第一个示例中,我做错了什么?


答案 1

实现此目的的一种更简洁的方法是提供初始值作为以下参数的第二个参数:reduce

var arr = [{x:1}, {x:2}, {x:4}];
var result = arr.reduce(function (acc, obj) { return acc + obj.x; }, 0);
console.log(result);  // 7

第一次调用匿名函数时,它被调用并返回 。下次,它被调用并返回 。然后调用 它,最后返回。(0, {x: 1})0 + 1 = 1(1, {x: 2})1 + 2 = 3(3, {x: 4})7

这还处理数组为空的情况,返回 。0


答案 2

在第一次迭代之后,您将返回一个数字,然后尝试获取它的属性以添加到下一个对象,该对象和数学涉及的结果。xundefinedundefinedNaN

尝试返回一个包含属性的对象,该属性的 x 属性之和为参数:x

var arr = [{x:1},{x:2},{x:4}];

arr.reduce(function (a, b) {
  return {x: a.x + b.x}; // returns object with property x
})

// ES6
arr.reduce((a, b) => ({x: a.x + b.x}));

// -> {x: 7}

从评论中添加的解释:

每次迭代的返回值在下一次迭代中用作变量。[].reducea

迭代 1:、 、在迭代 2 中分配给a = {x:1}b = {x:2}{x: 3}a

迭代 2:、 .a = {x:3}b = {x:4}

您的示例的问题在于您返回的是一个数字文本。

function (a, b) {
  return a.x + b.x; // returns number literal
}

迭代 1:、,与下一次迭代相同a = {x:1}b = {x:2}// returns 3a

迭代 2:,返回a = 3b = {x:2}NaN

数字文本(通常)没有一个称为的属性,因此它是和返回的,并且总是3xundefinedundefined + b.xNaNNaN + <anything>NaN

澄清:我更喜欢我的方法而不是这个线程中的其他顶部答案,因为我不同意传递一个可选参数来减少一个幻数来取出一个数字基元的想法。它可能会导致更少的行,但imo它的可读性较差。