JavaScript’s Array.prototype.reduce()


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']

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.

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
prev cur ind arr
Step 1 0 1 0 [1,2,3]
Step 2 1 2 1 [1,2,3]
Step 3 3 3 2 [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
prev cur ind arr
Step 1 1 2 1 [1,2,3]
Step 2 3 3 2 [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

Advertisements

5 thoughts on “JavaScript’s Array.prototype.reduce()

  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 Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s