Why do I need to use reduce method in Javascript
Tags: javascript, programming
Published: 2023-03-25 14:05:53

> Also available on my [blog](https://nikolasbarwicki.com/articles/why-do-i-need-to-use-reduce-method-in-javascript)

## 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:
```javascript
map([🌽, 🐮, 🐔], cook) => [🍿, 🍔, 🍳]

filter([🍿, 🍔, 🍳], isVegetarian) =>  [🍿, 🍳]

reduce([🍿, 🍳], eat) => 💩
```

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`:

```javascript
const order = [
    { product: '👘', price: 21 },
    { product: '👜', price: 37 },
    { product: '🦺', price: 69 },
];

let total = 0; // 127

for (const item of order) {
    total += item.price
}
```

`reduce` solves the same problem in a convenient one-liner:
```javascript
const total = order.reduce((total, item) => total + item.price, 0) // 127
```

## 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 🍳:

```javascript
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"}
]
```

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

// alternative way
result = ingredient.lenght; // 4
```

### Sum calories of all ingredients
```javascript
result = ingredients.reduce((acc, item) => acc += item.calories, 0) // 580

// alternative way
// .reduce is problably the best solution in this case
```

### Array of ingredients names
```javascript
result = ingredients.reduce((acc, item) => [...acc, item.name], []) // [ 'eggs', 'butter', 'bacon' ]

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


### Count occurrences
```javascript
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");
```

### Group by diet type
```javascript
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"); 
```

### Ingredients lookup by ids
```javascript
result = ingredients.reduce((acc, item) => {
  return {...acc, [item.id]: item}
}, {})

/* 
{
    '1': {
        id: 1,
        name: 'egg 🥚',
        calories: 140,
        diet: 'vegetarian'
},
    '2': {
        id: 2,
        name: 'egg 🥚',
        ... 
*/
```
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
```javascript
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
```

## 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.