Javascript减少对象数组

说我想对a.x中的每个元素求和arr

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

我有理由相信斧头在某些时候是不确定的。

以下工作正常

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

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

神乐十三2020/03/23 14:20:51

您不应该将ax用作累加器,而是可以像`arr = [{x:1},{x:2},{x:4}]这样操作

arr.reduce(function(a,b){a + bx},0)`

十三小宇宙2020/03/23 14:20:51

返回所有x道具的总和

arr.reduce(
(a,b) => (a.x || a) + b.x 
)
番长猴子2020/03/23 14:20:51

减少功能迭代集合

arr = [{x:1},{x:2},{x:4}] // is a collection

arr.reduce(function(a,b){return a.x + b.x})

转换为:

arr.reduce(
    //for each index in the collection, this callback function is called
  function (
    a, //a = accumulator ,during each callback , value of accumulator is 
         passed inside the variable "a"
    b, //currentValue , for ex currentValue is {x:1} in 1st callback
    currentIndex,
    array
  ) {
    return a.x + b.x; 
  },
  accumulator // this is returned at the end of arr.reduce call 
    //accumulator = returned value i.e return a.x + b.x  in each callback. 
);

在每个索引回调期间,将变量“累加器”的值传递到回调函数中的“ a”参数中。如果我们不初始化“累加器”,则其值将是不确定的。调用undefined.x会给您错误。

要解决此问题,请使用上面显示的Casey答案将0初始化为“累加器”

为了了解“ reduce”功能的内在,我建议您看一下该功能的源代码。Lodash库具有reduce函数,其功能与ES6中的reduce函数完全相同。

这里是链接: 减少源代码

飞云2020/03/23 14:20:51

第一步,它将正常工作,因为will的值为a1 will 的值为b2,但是由于将返回2 + 1,而在下一步中,of的值b将是返回值from step 1 i.e 3,因此b.x将是不确定的。 .and undefined + anyNumber将为NaN,这就是为什么要得到该结果的原因。

相反,您可以尝试通过将初始值设置为零(即

arr.reduce(function(a,b){return a + b.x},0);

乐米亚2020/03/23 14:20:51

如果您有一个包含大量数据的复杂对象(如对象数组),则可以采用逐步的方法来解决此问题。

例如:

const myArray = [{ id: 1, value: 10}, { id: 2, value: 20}];

首先,您应该将数组映射到您感兴趣的新数组,在此示例中,它可能是新的值数组。

const values = myArray.map(obj => obj.value);

此回调函数将返回一个仅包含原始数组中值的新数组,并将其存储在值const上。现在,您的值const是一个像这样的数组:

values = [10, 20];

现在,您可以执行还原了:

const sum = values.reduce((accumulator, currentValue) => { return accumulator + currentValue; } , 0);

如您所见,reduce方法多次执行回调函数。对于每次,它都会获取数组中该项的当前值,并与累加器求和。因此,要正确求和,需要将累加器的初始值设置为reduce方法的第二个参数。

现在您有了新的const和,其值为30。

伽罗理查德2020/03/23 14:20:51

在减少的每一步中,您都不会返回新{x:???}对象。因此,您需要执行以下操作:

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

或者你需要做

arr = [{x:1},{x:2},{x:4}]
arr.reduce(function(a,b){return {x: a.x + b.x}; }) 
斯丁2020/03/23 14:20:51

其他人回答了这个问题,但我想我会采用另一种方法。您可以直接映射(从ax到x)并缩小(添加x),而不是直接求和ax。

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

诚然,它可能会稍慢一些,但我认为值得一提。

小卤蛋2020/03/23 14:20:51

第一次迭代后,您将返回一个数字,然后尝试获取该数字的属性x以将其添加到下一个对象中,该对象是undefined和数学,涉及到undefined结果NaN

尝试返回一个对象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}

从注释中添加了说明:

每次迭代的返回值[].reduce用作a下一次迭代变量。

迭代1: ,a = {x:1} 分配给在迭代2b = {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

许多文字3不(通常)有一个叫做财产x所以它undefinedundefined + b.x回报NaN,并NaN + <anything>始终NaN

Clarification: I prefer my method over the other top answer in this thread as I disagree with the idea that passing an optional parameter to reduce with a magic number to get out a number primitive is cleaner. It may result in fewer lines written but imo it is less readable.

神乐卡卡西2020/03/23 14:20:51

一种更清洁的方法是通过提供一个初始值:

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

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