Search code examples
javascriptfunctional-programmingreduce

How to call reduce on an array of objects to sum their properties?


Say I want to sum a.x for each element in arr.

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

I have cause to believe that a.x is undefined at some point.

The following works fine

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

What am I doing wrong in the first example?


Solution

  • After the first iteration your're returning a number and then trying to get property x of it to add to the next object which is undefined and maths involving undefined results in NaN.

    try returning an object contain an x property with the sum of the x properties of the parameters:

    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}
    

    Explanation added from comments:

    The return value of each iteration of [].reduce used as the a variable in the next iteration.

    Iteration 1: a = {x:1}, b = {x:2}, {x: 3} assigned to a in Iteration 2

    Iteration 2: a = {x:3}, b = {x:4}.

    The problem with your example is that you're returning a number literal.

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

    Iteration 1: a = {x:1}, b = {x:2}, // returns 3 as a in next iteration

    Iteration 2: a = 3, b = {x:2} returns NaN

    A number literal 3 does not (typically) have a property called x so it's undefined and undefined + b.x returns NaN and NaN + <anything> is always 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.