This post is a basic walkthrough of JavaScript's map, filter, and reduce methods that provides practical use cases of functional programming in JavaScript.
What do they all have in common?
- All three functions are array methods (i.e. methods you can call on your array variables).
- The returned value in each function is a new array containing the result of the operations performed on the original array in a function you provide.
Map
- The
map()
method allows you iterate over each element in your array, and then manipulate each element in any desired way through the use of a provided function. - The provided function be an anonymous function, or a named function.
- It is very important to note that you want to use the
map()
method when you are expecting a return value from your function. Otherwise, it is recommended to use JavaScript'sforEach()
method when you want to modify the original array. - TL;DR -
map()
is afor
loop with a return value.
Basic Example
- This is a simple example provided by the MDN webpage on the
map()
method
const evenNumbers = [2, 4, 6]
const result = evenNumbers.map(currentValue => currentValue * 2)
// result = [4, 8, 12]
Practical Use Case
- This is an example you will often encounter where an API call returns an array of objects containing information about your users.
- The goal here is to extract the list of names from the response received from your API.
const users = [
{
'name': 'John Doe',
'address': 'Wellington St, Ottawa, ON K1A 0A9'
},
{
'name': 'Jane Doe',
'address': '1600 Pennsylvania Ave NW, Washington, DC 20500'
},
{
'name': 'Hannibal Lecter',
address: '10800 97 Ave NW, Edmonton, AB T5K 2B6'
}]
const names = users.map(currentItem => {
return currentItem['name']
})
// names = ['John Doe', 'Jane Doe', 'Hannibal Lecter']
Filter
- Similar to the
map()
method, thefilter()
method allows you to iterate over the elements of your array. - Although, the difference in this case is that
filter()
returns values that pass some test case provided.
Basic Example
- This is another simple example provided by the MDN webpage on the
filter()
method.
const numbers = [2, 4, 6, 11, 12, 33]
const evenNumbers = numbers.filter(x => x % 2 === 0)
// evenNumbers = [2, 4, 6, 12]
Practical Use Case
- Similar to the previous example, this is a situation where an API call returns an objects containing information about your users.
- The goal is to extract the names of users living outside the United States from the response received back from your API.
- The goal is to extract the names of users living outside of the United States form the response received back from your API.
const users = [
{
'name': 'John Doe',
'address': 'Wellington St, Ottawa, ON K1A 0A9',
'country': 'Canada'
},
{
'name': 'Jane Doe',
'address': '1600 Pennsylvania Ave NW, Washington, DC 20500',
'country': 'United States'
},
{
'name': 'Hannibal Lecter',
'address': '10800 97 Ave NW, Edmonton, AB T5K 2B6',
'country': 'Canada'
}]
const expatriates = users.filter(currentItem => {
return currentItem['country'] !== 'United States'
})
/* expatriates = [
{
name: 'John Doe',
address: 'Wellington St, Ottawa, ON K1A 0A9',
country: 'Canada'
},
{
name: 'Hannibal Lecter',
address: '10800 97 Ave NW, Edmonton, AB T5K 2B6',
country: 'Canada'
}]
*/
- Using this code snippet alone will not suffice if we are attempting to obtain an array containing names alone.
- Therefore, building on the previous knowledge we acquired about the
map()
method, we will need one more function call.
const expatriateNames = expatriates.map(currentValue => {
return currentValue['name']
})
// expatriateNames = ['John Doe', 'Hannibal Lecter']
Reduce
- As the name suggests, the
reduce()
method will accept an array containing multiple values and "reduce" them down into a single return value.
Syntax
array.reduce((accumulator, current) => {}, initialValue)
Basic Example
- In this particular example, we are attempting to iterate over the elements of an array and sum them up.
const array = [1, 2, 3]
const result = array.reduce((previousValue, currentValue) => {
return previousValue + currentValue
})
// result = 6
Practical Use Case
- The previous practical use case provided for the
filter()
is less than ideal as we had to rely on two different function calls to obtain our desired result. - In this implementation, we have the same goal as previous, extract the list of names of users living outside the United States from our response received from our API.
- In this case, we can reduce both
filter()
andmap()
method calls into a single function using thereduce()
method.
const users = [
{
'name': 'John Doe',
'address': 'Wellington St, Ottawa, ON K1A 0A9',
'country': 'Canada'
},
{
'name': 'Jane Doe',
'address': '1600 Pennsylvania Ave NW, Washington, DC 20500',
'country': 'United States'
},
{
'name': 'Hannibal Lecter',
'address': '10800 97 Ave NW, Edmonton, AB T5K 2B6',
'country': 'Canada'
}]
const expatriates = users.reduce((result, user) => {
// filter() equivalent
if (user['country'] === 'United States') {
return result
}
// map() equivalent
result.push(user['name'])
return result
}, initialValue = [])
- In this implementation, we do not add any value to the accumulator array, in this case we have called it
result
, thus successfully filtering out users who live outside the United States. - Next, once we have passed the initial
if
statement check, we add the name of the user to theaccumulator
array. - It is important that note that while you are able to return a single output from a reduce function, that return value can be an array by initializing the initial value to an empty array.
- Perhaps, my favourite explanation of the
reduce()
method suggested thinking of theaccumulator
as the previous value.
Credits
- This post would not have been possible without these wonderful tools and content creators
Discussion
Ideally, you shouldn't modify the original array at all. Funtional programming encourages immutability. From a strictly functional perspective you should really only use
forEach()
for IO operations, like changing the DOM.I appreciate how you've taken this explanation upon yourself. I think there's a revision in here, though;
reduce
is afor
with a return value,map
is a specializedreduce
that gives back a new array.Quite literally, anything you can do with a
for
loop, you can do withreduce
That's an interesting point that I hadn't considered, I'll update the post to reflect that!
The filter example should return the even numbers. Isn't it?
You're right, I've updated the typo!