Map Reduce in JavaScript

There seem to be a lot of people who believe using map and reduce to loop through lists of items produces more readable code.

I want to figure out how to do this, since I usually use for loops.

The concept is you provide a function that performs an operation on each item in an array. Executing this function for each element produces a new list (map) or a single value (reduce).

Map / Reduce?

map and reduce are two functions provided on the Array class in JavaScript. They serve a different purpose, but are of a similar flavour.

Not about NoSql Databases

When I hear the words "map" and "reduce", I always think of NoSql. But it has nothing to do with that. The reason these two words trigger that association is because of another system called "MapReduce":

Not this: A staple of the Hadoop ecosystem is MapReduce, a computational model that basically takes intensive data processes and spreads the computation across a potentially endless number of servers (generally referred to as a Hadoop cluster).

Source: datajobs.com

Map

When you "map" elements in an array, you perform a transformation on each of the elements and you get a new array, with the transformed elements.

For example, if we want a second array, with each element multiplied by two:

var myList = [1, 2, 3];
var myListMultiplied = myList.map(function (element) { return element * 2 });
// myList will be [1, 2, 3]
// myListMultiplied will be [2, 4, 6]

The provided function is: function (element) { return element * 2 }

The equivalent with a for loop:

var myList = [1, 2, 3];
var myListMultiplied = [];
for (var i = 0; i < myList.length; i++) {
  myListMultiplied[i] = myList[i] * 2;
}

Reduce

The "reduce" function takes the elements as input, and produces a single output. An example would be a sum of all elements in the array:

var myList = [1, 2, 3];
var sum = myList.reduce(function (total, element) { return total + element; });
// sum will have the value 1 + 2 + 3 = 6

The equivalent in a for loop:

var myList = [1, 2, 3];
var sum = 0;
for (var i = 0; i < myList.length; i++) {
  sum += myList[i];
}
// sum will have the value 1 + 2 + 3 = 6

Arrow functions

To avoid having to declare inline functions a lot, arrow functions can help. Our two examples from above, changed to use the arrow notation:

myList.map(element => element * 2);
myList.reduce((total, element) => total + element);

This way, you avoid writing function and return a lot.

Then the two examples look like this:

var myList = [1, 2, 3];
var myListMultiplied = myList.map(element => element * 2);
var myList = [1, 2, 3];
var sum = myList.reduce((total, element) => total + element);

Filter

There is another function called filter.

It will take only those elements out of an array for which a given function returns true:

var myList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var bigNumbers = myList.filter((element) => element > 5);
// bigNumbers will be [6, 7, 8, 9, 10]

For comparison, here's the same functionality with a for loop:

var myList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var bigNumbers = [];
for (var i = 0; i < myList.length; i++) {
  if (myList[i] > 5) { bigNumbers.push(myList[i]); }
}
// bigNumbers will be [6, 7, 8, 9, 10]

Browser Support

The map, reduce and filter functions are supported on all major browsers, even on Internet Explorer 9.

The arrow functions are not supported in Internet Explorer, but apart from that there is support in most major browsers:

  • Chrome as of Version 45
  • Firefox as of Version 22

Conclusion

Using the map, reduce and filter functions, in combination with the arrow notation certainly makes code easier to write. And it is much shorter to read.

However, people who are unfamiliar with these functions may have to think a little bit harder when reading that code.

I wasn't convinved when I started this post, but writing it up now I think I may be using map / reduce more often.

Sources