Why do I need to use reduce method in Javascript

nikolasbarwicki

Nikolas โšก๏ธ

Posted on March 25, 2023

Why do I need to use reduce method in Javascript

Also available on my blog

I don't use reduce method and I'm good with it

Probably you already are a pretty experienced Javascript developer but you have not used .reduce() method in your
production code yet'. You still can't find the right use case for this method.

What does it do and why do I want to use it? - you may ask.

In this article I'll show you many code examples where .reduce() is a great choice.

Basics

When you need to iterate over an array you can use for, forEach or for..of. When you need to iterate and return
data (most of the time - modified) data for each element you probably would use map.

reduce is a little different comparing to the methods listed above. It is used to calculate a single value based
on the array.

Here is a little example showing the main differences:

map([๐ŸŒฝ, ๐Ÿฎ, ๐Ÿ”], cook) => [๐Ÿฟ, ๐Ÿ”, ๐Ÿณ]

filter([๐Ÿฟ, ๐Ÿ”, ๐Ÿณ], isVegetarian) =>  [๐Ÿฟ, ๐Ÿณ]

reduce([๐Ÿฟ, ๐Ÿณ], eat) => ๐Ÿ’ฉ
Enter fullscreen mode Exit fullscreen mode

I hope you already get the basics, right?

Basic use case

The best example that meets our assumptions of calculating a single value based on the array is getting the total of some order.
Below you can see the array of products with its prices. The easiest way to calculate the order's total would be using
for..of:

const order = [
    { product: '๐Ÿ‘˜', price: 21 },
    { product: '๐Ÿ‘œ', price: 37 },
    { product: '๐Ÿฆบ', price: 69 },
];

let total = 0; // 127

for (const item of order) {
    total += item.price
}
Enter fullscreen mode Exit fullscreen mode

reduce solves the same problem in a convenient one-liner:

const total = order.reduce((total, item) => total + item.price, 0) // 127
Enter fullscreen mode Exit fullscreen mode

Plenty of extra examples

In this section I'll show you many other examples of using reduce. Please keep in mind that many of these can, and
should be, rewritten using more appropriate and more efficient array methods.

Let's start with the list of ingredients for a scrambled eggs ๐Ÿณ:

const ingredients = [
    {id: 1, name: "egg ๐Ÿฅš", calories: 140, diet: "vegetarian"},
    {id: 2, name: "egg ๐Ÿฅš", calories: 140, diet: "vegetarian"},
    {id: 3, name: "butter ๐Ÿงˆ", calories: 90, diet: "vegetarian"},
    {id: 4, name: "bacon ๐Ÿฅ“", calories: 210, diet: "carnivore"}
]
Enter fullscreen mode Exit fullscreen mode

Count ingredients

result = ingredients.reduce((acc, item) => acc + 1, 0); // 4

// alternative way
result = ingredient.lenght; // 4
Enter fullscreen mode Exit fullscreen mode

Sum calories of all ingredients

result = ingredients.reduce((acc, item) => acc += item.calories, 0) // 580

// alternative way
// .reduce is problably the best solution in this case
Enter fullscreen mode Exit fullscreen mode

Array of ingredients names

result = ingredients.reduce((acc, item) => [...acc, item.name], []) // [ 'eggs', 'butter', 'bacon' ]

// alternative way
result = ingredients.map(item => item.name); // [ 'eggs', 'butter', 'bacon' ]
Enter fullscreen mode Exit fullscreen mode

Count occurrences

result = ingredients.reduces((acc, item) => {
    return {...acc, [person.age]: (acc[person.age] ||0) + 1} // { 'egg ๐Ÿฅš': 2, 'butter ๐Ÿงˆ': 1, 'bacon ๐Ÿฅ“': 1 }
}, {})

// alternative way
// using lodash
_.countBy(ingredients, "name");
Enter fullscreen mode Exit fullscreen mode

Group by diet type

result = ingredients.reduce((grouped, item) => {
    const {diet, name} = item;
    if(grouped[diet] == null) grouped[diet] = [];
    grouped[diet].push(name)
    return grouped
}, {}) // {vegetarian: [ 'egg ๐Ÿฅš', 'egg ๐Ÿฅš', 'butter ๐Ÿงˆ' ], carnivore: [ 'bacon ๐Ÿฅ“' ]}

// alternative way (need to be transformed to return just names)
_.groupBy(ingredients, "diet"); 
Enter fullscreen mode Exit fullscreen mode

Ingredients lookup by ids

result = ingredients.reduce((acc, item) => {
  return {...acc, [item.id]: item}
}, {})

/* 
{
    '1': {
        id: 1,
        name: 'egg ๐Ÿฅš',
        calories: 140,
        diet: 'vegetarian'
},
    '2': {
        id: 2,
        name: 'egg ๐Ÿฅš',
        ... 
*/
Enter fullscreen mode Exit fullscreen mode

Creating such object gives us an efficiency advantage when we want to access one specific element - we don't have to
iterate over a whole array looking for matching element.

Get the ingredient with the most calories

result = ingredients.reduce((acc, item) => {
  if (acc === null || item.calories > acc) return item.calories
  return acc
}, null) // 210

// alternative way
result = Math.max(...ingredients.map(item => item.calories)) // 210
Enter fullscreen mode Exit fullscreen mode

Summary

After reading and understanding all of these examples I'm sure that you know in which cases reduce would be the best solution.

Using reduce seems to be a great way to solve some problems in Javascript but at the same time there is also opposite
perspective among many developers. Jake Archibald (@jaffathecake) posted a tweet about this:

All code using array.reduce should be rewritten without array.reduce so it's readable by humans mutes thread

Now it is only your responsibility to decide whether you want to incorporate reduce method to your everyday life or
maybe you want to stick to Jake's perspective and use other array methods combined with widely known lodash for example.

๐Ÿ’– ๐Ÿ’ช ๐Ÿ™… ๐Ÿšฉ
nikolasbarwicki
Nikolas โšก๏ธ

Posted on March 25, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

ยฉ TheLazy.dev

About