I was playing around with the nodeschool's functional javascript tutorial. One neat module is on reduce.

Reduce

Here is the summary given in the MDN docs.

The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) has to reduce it to a single value.

That sounds interesting. Let's say you had an array and wanted to sum all the values in the array. The simple solution would be to simply create a for loop and iterate over every value summing them together. A better way is to use reduce like so.

[0,1,2,3,4].reduce(function(previousValue, currentValue, index, array){
  return previousValue + currentValue;
});

The function callback would be invoked four times. Each time adding the previousValue to the currentValue. The last callback invocation would return 10.

Keep in mind that the reduce syntax is as follows.

arr.reduce(callback,[initialValue])  

The initial value is an optional parameter. If added this initial value will equal the previous value during the first invocation. So in the example above if the initial value was 10, for example, the final output would be 20.

A More Interesting Example

Let's say you have a list of words in an array. And you wanted to count how many times each word appears in the array.

var inputWords = ['Apple', 'Banana', 'Apple', 'Durian', 'Durian', 'Durian']

console.log(countWords(inputWords))

// =>
// {
//   Apple: 2,
//   Banana: 1,
//   Durian: 3
// }

With only using reduce you can create an object like this. First let's take a look at countWords.

function countWords(arr) {  
//do something
}

This function is going to simply take an array and return an object with the counts for each word.

We know from our last example that reduce uses a callback that contains four parameters. Previous, current, index and the original array. We can use this to our advantage.

One technique in solving this problem is to use an associative array. That way we can store each name in the array as a key. We then simply increment each iteration if that key appears again. The first two parameters to the callback is the previous and next items in the array. In the example below we are calling them countMap and word.

function countWords(arr) {  
  return arr.reduce(function(countMap, word) {
    countMap[word] = ++countMap[word] || 1 
    // increment or initialize to 1
    return countMap
  }) 
}

In the above example we use the reduce function to start counting each word using the associative array. Every invocation the countMap[word] is initialized to one or incremented.

One issue with the above examples is that we left the initialization blank. To make the function work correctly we need to make sure we initialize countMap with a {}.

function countWords(arr) {  
  return arr.reduce(function(countMap, word) {
    countMap[word] = ++countMap[word] || 1 

    return countMap
  },{}) 
}

That's it. FYI reduce is only available in ECMA 5.1 or above. This may cause issues with older browsers. You can use something like es5-shim to give compatibility to older browsers.