How to start using array.reduce

Xerxes Nøble
3 min readJul 21, 2018

--

Through a lot of code reviews and StackOverflow answers, I’ve seen people use or suggest solutions that require chaining multiple array methods (specifically .filter().map() ).

When you run multiple operators of an array, you are iterating multiple arrays, and that can get inefficient pretty quick. I see reduce as something that can solve this problem and give you the freedom to build the array you were looking for while running as few iterations as possible.

Heres a little intro to how you can use reduce, a very powerful javascript list operator.

Lets say we have some data like this assigned to the variable “dogs":

const dogs = [
{
name: ‘Zoey’,
breed: ‘Labrador Retriever’
},
{
name: ‘Caesar’,
breed: ‘Chihuahua’
},
{
name: ‘Pedro’,
breed: ‘Dachshund’
},
{
name: ‘Lilly’,
breed: ‘Chihuahua’
}
]

If in your application, you need to get a list of names of dogs by their breed, you might think to do this:

const dogs [ … ]function dogsByBreed(breed) {
return dogs
// Filter a list of dogs that match
.filter(dog => dog.breed === breed)
// Create a new list of only names
.map(dog => dog.name)
}
const chihuahuas = dogsByBreed(‘Chihuahua’)
// [‘Caesar’, ‘Lilly’]

This isn’t an ideal solution for two reasons:
1. For each query, you need to iterate two lists. Once the entire list and again the filtered list.

2. You need to iterate the list every time you make a query.

Here is one approach using reduce:

const dogs [ … ]function dogsByBreed(breed) {
// Reduce a list of dog objects
return dogs.reduce((names, dog) => {
// If the dog breed matches, add to accumulator
if (dog.breed === breed) {
names.push(dog.name)
}
// return accumulator
return names
}, [])
}
const chihuahuas = dogsByBreed(‘Chihuahua’)
// [‘Caesar’, ‘Lilly’]

This solves the first problem of iterating multiple lists per query. However, we still need to iterate this list of dogs everytime. Lets fix that.

const dogs [ … ]// Create a object of dog names by breed
const dogsByBreed = dogs.reduce((breeds, dog) => {
// If breed already exists in object, add name to list
if (breeds[dog.breed]) {
breeds[dog.breed].push(dog.name)
// Else create list with dog name in it
} else {
breeds[dog.breed] = [dog.name]
}
// Return accumulator
return breeds
}, {})
/*dogsByBreed = {
‘Labrador Retriever’: [‘Zoey’],
‘Chihuahua’: [‘Caesar’, ‘Lilly’],
‘Dachshund’: [‘Pedro’]
}
*/const chihuahuas = dogsByBreed[‘Chihuahua’]
// [‘Caesar’, ‘Lilly’]

In this last example, notice that we passed an object in as the accumulator. We are only iterating the list once and creating a map of dogs by their breed. This way we can directly grab the list of names from the object we created.

This is obviously a very small and simple example of how powerful `reduce` can be. Some may argue that using the .filter().map() solution is much more clear, and while that may be true, it’s hard to argue the inefficiency when you have very long lists or a reactive UI that makes this query every time your state is changed.

Oh, here is a link to MDN docs on array.reduce

I’d love to hear comments on how you are using or plan to use array.reduce, or you can just tell me I’m completely wrong. Both are equally welcome :)

Thanks for reading!

--

--