You’ve probably used map, reduce, and other functional methods in Javascript before, but there are a few use cases you probably haven’t thought about much or used before. In this post, I’d like to go over these methods (and a few other surprises!) to show what’s possible.
Array#map
Map is the powerhouse of the cell, er, Javascript. It’s my favorite way to iterate over an array when I need a new value for each value in the array. In other words, if you need to transform an array element-by-element, map is the way to go. For example:
const squares = arr.map(i => Math.pow(i, 2));
You can also get the index as the second parameter of the callback, as in:
const nums = arr.map((i, idx) => {
if (idx % 2 === 0) {
return Math.pow(i, 2);
} else {
return Math.sqrt(i);
}
});
This is a contrived example, but you get the picture. It gets more useful, though, when you factor in…
Array#reduce
Reduce is an efficient, expressive way to get a single value from a list of values.
If you didn't know about reduce, you might do something like this:
let storyMap = {};
stories.map(story => {
storyMap[story.slug] = story;
});
But with reduce, this can be made into:
const storyMap = stories.reduce((acc, story) => {
acc[story.slug] = story;
return acc;
}, {});
This, of course, is a contrived example, but you can clearly see how a more complex object might be built out of such a call. In this case,
acc
stands for "accumulator", the value that will eventually be passed out of reduce and into storyMap
. If you pass a second parameter to reduce, as we have, that sets the initial value of the accumulator.Let's look at a few real examples from the Hacker Noon codebase:
const words = stories.map(story => story.wordCount || story.words)
.filter(wordCount => !!wordCount)
.reduce((a, b) => { return a + b }, 0);
This example is fairly straightforward. We get the word count from both 2.0 and archived (1.0) stories, filter out any falsy/null values, then sum the resulting array using reduce.
As you can see, we make heavy use of map, filter, and reduce:
const storyMap = stories.reduce((acc, story) => {
acc[`/${story.slug}`] = story;
return acc;
}, {});
const storyMetrics = data.rows.reduce((acc, row) => {
const pathname = row.dimensions[0];
const story = storyMap[pathname];
if (!story) { return acc; }
const [pageviews, timeRead, avgTimeRead] = row.metrics[0].values;
const metrics = { pageviews, time: timeRead };
acc[story.id] = metrics;
return acc;
}, {});