reduce function for array in javascript

Parameters

callback
Function to execute on each value in the array, taking four arguments:

previousValue
The value previously returned in the last invocation of the callback, or initialValue, if supplied. (See below.)
currentValue
The current element being processed in the array.
index
The index of the current element being processed in the array.
array
The array reduce was called upon.
initialValue
Optional. Object to use as the first argument to the first call of the callback.
[0, 1, 2, 3, 4].reduce(function(previousValue, currentValue, index, array) {
  return previousValue + currentValue;
}, 10);

Examples

 Example: Flatten an array of arrays

var flattened = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) {
  return a.concat(b);
});
// flattened is [0, 1, 2, 3, 4, 5]

 

Consider the case of a library system which needs to show potential donors its effectiveness at spreading knowledge. In order to do that, it must determine how many book-checkouts there were last year. (Not total of all checkouts, since a single checkout may be for more than one book.)

Their data is stored in an object like this:

var books = [
    {
        title: "Showings",
        author: "Julian of Norwich",
        checkouts: 45
    },
    {
        title: "The Triads",
        author: "Gregory Palamas",
        checkouts: 32
    },
    {
        title: "The Praktikos",
        author: "Evagrius Ponticus",
        checkouts: 29
    }
];

The traditional C-style way to get at that number would be something like this:

var bookCheckouts = 0;

for (var i = 0; i < books.length; i++) {
    bookCheckouts = bookCheckouts + books[i].checkouts;
}

But using reduce, we can think more directly about the problem itself:

// Get an array of checkout values only
var bookCheckouts = books.map(function(item) {
    return item.checkouts;
});

// Sum the array's values from left to right
var total = bookCheckouts.reduce(function(prev, curr) {
    return prev + curr;
});

While it may look a little foreign at first, this example is more explicit about the problem than thefor version is. Namely, dealing only with the checkouts property, and totaling them. And if you are familiar with the idioms, you can make it almost as concise.

// Get total of book checkouts
var total = books
            .map(function(b) { return b.checkouts; })
            .reduce(function(p, c) { return p + c; });

So how does that reduce method work? It takes an array of values and executes the function (almost!) once for each item in the array. The value of prev is the result of the calculations up to this point. Let’s take a look:

[1, 2, 3].reduce(function(prev, curr, index) {
    console.log(prev, curr, index);
    return prev + curr;
});

// Outputs:
// 1, 2, 1
// 3, 3, 2
// 6

As you can see, the callback actually didn’t iterate over the first element of the array. Instead,prev was set to the value of the first element. It has to work that way because otherwisereduce wouldn’t have a starting value for prev.

The function ran three times, but on the last call, it wasn’t given a current element since there were no elements left in the array. That behavior is a little confusing to read through, but is quite easy to use.

Here is another example:

[1, 2, 3].reduce(function(prev, curr, index) {
    console.log(prev, curr, index);
    return prev + curr;
}, 100);

// Outputs:
// 100 1 0
// 101 2 1
// 103 3 2
// 106

In addition to the callback function, we also passed in an initial value for prev. You’ll note that in this case, the callback did iterate over the first element in the array, since it had an initial value to work with.

It should be noted that your callback function also has access to the array itself as a parameter.

[1, 2, 3].reduce(function(prev, curr, index, arr) {
    // Do something here
});

Is reduce only good for working with numbers? By no means. Consider this:

var relArray = [
    ["Viola", "Orsino"],
    ["Orsino", "Olivia"],
    ["Olivia", "Cesario"]
];

var relMap = relArray.reduce(function(memo, curr) {
    memo[curr[0]] = curr[1];
    return memo;
}, {});

// Outputs: {
//    "Viola": "Orsino",
//    "Orsino": "Olivia",
//    "Olivia": "Cesario"
// }
console.log(relMap);

This time we used reduce to transform the relationship data from an array of arrays into an object where each key value pair describes the relationship. You’ll also see that instead of naming the parameter prev as I did before, I used the term memo. That’s because in this case, memo is a more descriptive name for the actual value being passed in (an object collecting new properties.)

The reduce method is good for any sort of situation where we want to take an array and boil it down into a new value in steps that have access to one or two of the array elements at a time.

Want to use reduce in IE8 or IE7? Take a look at the Underscore and Lo-Dash libraries.

 

FROM HERE

Advertisements

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