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.