A cleaner way to accomplish this is by providing an initial value as the second argument to reduce:
Copyvar arr = [{x:1}, {x:2}, {x:4}];
var result = arr.reduce(function (acc, obj) { return acc + obj.x; }, 0);
console.log(result); // 7
Run code snippetEdit code snippet Hide Results Copy to answer Expand
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.
A cleaner way to accomplish this is by providing an initial value as the second argument to reduce:
Copyvar arr = [{x:1}, {x:2}, {x:4}];
var result = arr.reduce(function (acc, obj) { return acc + obj.x; }, 0);
console.log(result); // 7
Run code snippetEdit code snippet Hide Results Copy to answer Expand
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:
Copyvar 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.
Copyfunction (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.
How to reduce array of objects to array
Learning array.reduce() method, i need some help to understand it.
Reduce array of nested objects?
javascript - Reduce array of objects into object of arrays - Code Review Stack Exchange
Videos
We've got a readability issue here. This is the horror we all have to face when we overuse the new "concise" ES6 syntax. I had to read the code at least 3 times to understand what it was doing (and forgot ... is spread).
If you're worried about code size, let the minifier do its job. Code is for programmers to understand. The verbose version of it isn't that bad. It's not like it's not going to run in older browsers.
var result = rows.reduce(function(result, item){
result[item.k] = (result[item.k] || []).concat(item);
return result;
}, {});
If you are a fan of FP, you should use a functional library, e. g. Ramda. With it, you can create your transforming function points-free style:
import { compose, mapObj, map, prop, groupBy } from 'ramda';
const f = compose(
mapObj(
map(prop('v'))
),
groupBy(prop('k'))
);
Proof: http://jsfiddle.net/03m7r7be/