0

I am seeing a strange behaviour with the reduce function in javascript.

I have an array of objects, made like this:

[ { a:1 }, {a:2}, ... ]

I need the sum of the a property inside every object, so I wrote this:

const array = [{a:1}, {a:2}];
const reducer = (accumulator, currentValue) => accumulator.a + currentValue.a;
console.log(array.reduce(reducer));

This works as expected.

If I try to run the same code with an array containing a single object, I get that object as the result of the reduce call (and this is expected behaviour), so I added a default value to the reduce function call like this:

const array = [{a:1}];
const reducer = (accumulator, currentValue) => accumulator.a + currentValue.a;
console.log(array.reduce(reducer, {a: 0}));

And this also works like a charm.

I would expect to be able to run the second version of the reduce call with an array with more than one element, such as:

const array = [{a:1}, {a:2}];
const reducer = (accumulator, currentValue) => accumulator.a + currentValue.a;
console.log(array.reduce(reducer, {a: 0}));

But this returns NaN and I don't understand why. Could anyone please explain me?

whites11
  • 12,008
  • 3
  • 36
  • 53
  • Your 1st attempt won't work with `const array = [{a:1}, {a:2}, {a:3}];`. Because after the 1st iteration, accumulator will be a number. – Ori Drori Mar 30 '18 at 13:22
  • 1
    Does this answer your question? [Array reduce function is returning NAN](https://stackoverflow.com/questions/39698450/array-reduce-function-is-returning-nan) – Sebastian Simon Apr 09 '21 at 14:23
  • Or better: [Javascript reduce on array of objects](https://stackoverflow.com/q/5732043/4642212). – Sebastian Simon Apr 09 '21 at 14:31

3 Answers3

3

When using Array.reduce(), if you don't state an initial value, the 1st item of the array becomes the initial value. Since you want a number, and not an object as the result, initialize with 0. Since the accumulator is now a number, and not an object, use accumulator instead of accumulator.a in the function's body:

const array = [{a:1}, {a:2}, {a:3}];
const reducer = (accumulator, currentValue) => accumulator + currentValue.a;
console.log(array.reduce(reducer, 0));

You can also check if the accumulator is an object, and then try to access it's property, but I find it more confusing than simply stating an initial value:

const array = [{a:1}, {a:2}, {a:3}];
const reducer = (accumulator, currentValue) => (typeof accumulator === 'object' ? accumulator.a : accumulator) + currentValue.a;
console.log(array.reduce(reducer));
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
1

Your reducer returns a number value (sum of accumulator.a + currentValue.a) while your accumulator is an object.

Either initialize accumulator to 0 or return the accumulator itself, make it

const reducer = (accumulator, currentValue) => (accumulator.a += currentValue.a, accumulator);

Demo

const array = [{
  a: 1
}, {
  a: 2
}];
const reducer = (accumulator, currentValue) => (accumulator.a += currentValue.a, accumulator);
console.log(array.reduce(reducer, {
  a: 0
}));

Note

  • This reducer will return {"a":3}, but if you only want the sum value, print its property a

i.e.

console.log(array.reduce(reducer, {
  a: 0
}).a);
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
0

You need to change your reducer function as

const reducer = (accumulator, currentValue) => ({ a: accumulator.a + currentValue.a });

your orignal code doesn't work as you return a Number instead of an object whose property you were accessing.

vibhor1997a
  • 2,336
  • 2
  • 17
  • 37