I was working on a project where I needed to do an aggregate sum of a specific property of an array of objects. Consider the following:
var obj = [ { thread: 'An Essay on Javascript', comments: 9 }, { thread: 'An Essay on HTML', comments: 2 }, { thread: 'An Essay on CSS3', comments: 5 } ];
Let’s say you wanted to figure out the total sum of comments for all threads. You could do:
var total_comments = 0; for (var i = 0; i < obj.length; i++) { total_comments += obj[i].comments; };
Or, with the ECMA-262 standard in mind:
var total_comments = 0; obj.forEach(function (o) { total_comments += o.comments; });
Another method, however, is to use the map
and reduce
functions to accomplish the same thing. In this case, we'll utilize one line of code and leverage method chaining:
var total_comments = obj .map(function (o) { return o.comments; }) .reduce(function (p, c) { return p + c; }, 0);
In the above code, the reduce
function requires an array of values to perform the summation. For example:
// Returns 15; note that 0 is the initial value. [1, 2, 3, 4, 5].reduce(function (previousVal, currentVal) { return previousVal + currentVal; }, 0);
So, based on the variable obj
above, how do we get an array of values to feed to the reduce
function? The answer is to use the map
function:
// Returns [9, 2, 5]. obj.map(function (o) { return o.comments; });
Remember the map
function returns an array. In the above example, we're using the map
function to "pick" only the comments
property to build the array. So, conceptually, this is what's happening:
var total_comments = obj // Remember, obj contains: [{..., comments: 9}, {..., comments:2}, {..., comments:5}] .map(function (o) { return o.comments; }) // Map "picks" only the comments property to return [9, 2, 5] .reduce(function (p, c) { return p + c; }, 0); // Reduce then sums the [9, 2, 5] array elements
It's important to note, however, that this method is not compatible with IE8 (surprise). As a workaround, you could include map and reduce prototypes provided by the Mozilla Developer Network in your scripts.