Understanding reduce with JavaScript Arrays


Programming involves manipulating collections of various things. Operations on collections include aggregating values, conversion into other formats and data replacement.

Let’s take a sum of array elements using the typical imperative style.

function sum(arr) {
  var sum = 0,
  i = 0,
  len = arr.length;

  for(; i < len; i++){
     sum += arr[i];
  }
  return sum;
}

console.log(sum([1,2,3]));
//6

Here’s another example to flatten a 2-d array.

function flatten (coll){
    var arr = [],
    i = 0,
    len = coll.length;

    for(; i < len; i++){
        arr = arr.concat(coll[i]);
    }
    return arr;
}

var arr2 = [[1,2], ['a','b']];
console.log(flatten(arr2));
//[1,2,'a','b']

One liner (inpiration)

Array.prototype.concat.apply([], arr2);
//[1,2,'a','b']

Reducing by Folding

Both code snippets can be written more succinctly using the fold concept from functional programming. The snippets below leverage JavaScript’s Array.prototype.reduce to achieve the fold effect.

var sum = function (a, b) {
    return a + b;
};

total = [1,2,3].reduce(sum, 0);
console.log(total);
//6

var flttn = function (arr1, arr2) {
    return arr1.concat(arr2);
};

flt=[[1,2],['a','b']].reduce(flttn,[]);
console.log(flt);
//[1,2,'a','b']

Beautiful right? Let’s take it one step further, here is another example that shows the beauty of this approach.

var square = function (a) {
  return a * a;
}
sumSquares = [1,2,3].map(square)
    .reduce(sum,0);

console.log(sumSquares);
//14
//->(1*1) + (2*2) + (3*3)

Tip: This is the MapReduce concept (think Hadoop) – mapping and then reducing.

Now that you have seen the code; let’s examine the reduce method.

JavaScript’s Reduce Function Signature

The reduce function takes in a callback function and an initial value.

array.reduce(callback, initialValue)

InitialValue is the seed value used for the reduce operation and is optional.

The callback takes in four separate values (you can usually ignore the last two); the four values are the previousValue, currentValue, index and the array itself. It must return a value to be used in later calls to the reduce function otherwise you’ll get an undefined result.

reduceCallback(
  previousValue,
  currentValue,
  index,
  array)
  • previousValue: The accumulated value so far; it will be initalValue if provided otherwise it is the first element in array
  • currentValue: The current value in the array
  • index: The index of the current element in the array (optional)
  • array: The entire array (optional)

The example below is a verbose sum function to show what the various arguments are; the values are logged below in the table.

var sum2 = function (prev, cur, ind, arr){
 console.log(prev);
 console.log(cur);
 console.log(ind);
 console.log(arr);
 console.log("\n")
 return prev + cur;
};

[1,2,3].reduce(sum2, 0);
//6
 prevcurindarr
Step 1010[1,2,3]
Step 2121[1,2,3]
Step 3332[1,2,3]

Assuming the initial value was not set; then prev will be automatically set to the first element in the array for the initial call and the second element will be set to the cur value.

The code snippet below is traced out in the table below

[1,2,3].reduce(sum2);
//6
 prevcurindarr
Step 1121[1,2,3]
Step 2332[1,2,3]

Finally there is a reduceRight function too which processes the array from right to left; I still haven’t found quite a use for this.

Some more articles you might enjoy…

1. A peek into JavaScript’s Array.prototype.map and jQuery.map

2. Three Important JavaScript Concepts

6 thoughts on “Understanding reduce with JavaScript Arrays

  1. you can look at some scala examples as discussed in “https://www.coursera.org/course/progfun?from_restricted_preview=1&course_id=973439&r=https%3A%2F%2Fclass.coursera.org%2Fprogfun-005%2Flecture”

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.