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?
To sum a property in an array of objects:Initialize a sum variable, using the let keyword and set it to 0 . Call the forEach() method to iterate over the array. On each iteration, increment the sum variable with the value of the object.
reduce can use initial and return values of any type, which makes it very flexible. Let's explore how we can use it to perform some common tasks with plain objects.
The reduce() method executes a user-supplied "reducer" callback function on each element of the array, in order, passing in the return value from the calculation on the preceding element. The final result of running the reducer across all elements of the array is a single value.
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.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With