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

The best answers to the question “How to call reduce on an array of objects to sum their properties?” in the category Dev.

QUESTION:

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?

A cleaner way to accomplish this is by providing an initial value as the second argument to `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``````

The first time the anonymous function is called, it gets called with `(0, {x: 1})` and returns `0 + 1 = 1`. The next time, it gets called with `(1, {x: 2})` and returns `1 + 2 = 3`. It’s then called with `(3, {x: 4})`, finally returning `7`.

This also handles the case where the array is empty, returning `0`.

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}
``````

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.

Others have answered this question, but I thought I’d toss in another approach. Rather than go directly to summing a.x, you can combine a map (from a.x to x) and reduce (to add the x’s):

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

Admittedly, it’s probably going to be slightly slower, but I thought it worth mentioning it as an option.

TL;DR, set the initial value

Using destructuring

`arr.reduce( ( sum, { x } ) => sum + x , 0)`

Without destructuring

`arr.reduce( ( sum , cur ) => sum + cur.x , 0)`

With Typescript

`arr.reduce( ( sum, { x } : { x: number } ) => sum + x , 0)`

Let’s try the destructuring method:

``````const arr = [ { x: 1 }, { x: 2 }, { x: 4 } ]
const result = arr.reduce( ( sum, { x } ) => sum + x , 0)
console.log( result ) // 7``````

The key to this is setting initial value. The return value becomes first parameter of the next iteration.

# Technique used in top answer is not idiomatic

The accepted answer proposes NOT passing the “optional” value. This is wrong, as the idiomatic way is that the second parameter always be included. Why? Three reasons:

1. Dangerous
— Not passing in the initial value is dangerous and can create side-effects and mutations if the callback function is careless.

Behold

``````const badCallback = (a,i) => Object.assign(a,i)

const foo = [ { a: 1 }, { b: 2 }, { c: 3 } ]
const bar = foo.reduce( badCallback )  // bad use of Object.assign
// Look, we've tampered with the original array
foo //  [ { a: 1, b: 2, c: 3 }, { b: 2 }, { c: 3 } ]
``````

If however we had done it this way, with the initial value:

``````const bar = foo.reduce( badCallback, {})
// foo is still OK
foo // { a: 1, b: 2, c: 3 }
``````

For the record, unless you intend to mutate the original object, set the first parameter of `Object.assign` to an empty object. Like this: `Object.assign({}, a, b, c)`.

2 – Better Type Inference
–When using a tool like Typescript or an editor like VS Code, you get the benefit of telling the compiler the initial and it can catch errors if you’re doing it wrong. If you don’t set the initial value, in many situations it might not be able to guess and you could end up with creepy runtime errors.

3 – Respect the Functors
— JavaScript shines best when its inner functional child is unleashed. In the functional world, there is a standard on how you “fold” or `reduce` an array. When you fold or apply a catamorphism to the array, you take the values of that array to construct a new type. You need to communicate the resulting type–you should do this even if the final type is that of the values in the array, another array, or any other type.

Let’s think about it another way. In JavaScript, functions can be pass around like data, this is how callbacks work, what is the result of the following code?

`[1,2,3].reduce(callback)`

Will it return an number? An object? This makes it clearer

`[1,2,3].reduce(callback,0)`

Read more on the functional programming spec here: https://github.com/fantasyland/fantasy-land#foldable

# Some more background

The `reduce` method takes two parameters,

``````Array.prototype.reduce( callback, initialItem )
``````

The `callback` function takes the following parameters

``````(accumulator, itemInArray, indexInArray, entireArray) => { /* do stuff */ }
``````

For the first iteration,

• If `initialItem` is provided, the `reduce` function passes the `initialItem` as the `accumulator` and the first item of the array as the `itemInArray`.

• If `initialItem` is not provided, the `reduce` function passes the first item in the array as the `initialItem` and the second item in the array as `itemInArray` which can be confusing behavior.

I teach and recommend always setting the initial value of reduce.

You can check out the documentation at:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

Hope this helps!