# Reduce: the multitool of JavaScript array manipulation

A beginner-friendly guide into the JavaScript’s reduce method. Spiced up with
analogies and examples.

## Why reduce might be needed?

JavaScript provides some handy Array methods, like, `map`, `filter`, `includes`,
`some`, and `every`, just to mention a few.
[This guide to common array methods](/javascript-manipulating-objects-with-object-keys)
has examples of several of them working with object keys.

But there’s a sane limit of how many custom methods you can have in a language.
Thank goodness JavaScript is not like PHP, where you can just type a sentence
and slap parens at the end and et voilà, it probably does what you want:

```php
// Example of a typical native PHP function
plz_make_that_thing_like_backwards_and_then_tally_them_up_after()
```

**Rather than being a collection of functions**, JavaScript is a programming
languages which provides versatile methods like reduce. Reduce is the Swiss army
knife of array methods, a higher order function that lets you build your own
tools.

Higher order **function** is a **function** that takes a **function** as a
parameters.

## Reduce syntax

Perhaps a helpful way to look at `reduce` is to compare it to a `map`, it has
two differences:

```js
const foo = ['foo', 'bar'].map((currentValue, index, array) => {
  return // ...
})

const bar = ['foo', 'bar'].reduce((prevValue, currentValue, index, array) => {
  return // ...
}, {})
```

1. The callback has one extra argument: `prevValue`, also referred to as
   `accumulator`.
2. The method has a second parameter: `initialValue`, which is not always
   needed, but it can be for example an empty object `{}` or `0`.

**And this gives it two features `map` doesn’t have:**

1. Access to the previously processed values during the iteration, or another
   way of phrasing: reduce is able to keep track of the accumulated state
   internally.
2. Possibility to return other data type than array, like object, or anything
   really, int, string...

### Reduce arguments

`callback`

A function to execute on each element in the array, except for the first, if
    *no* initialValue is supplied.

`previousValue`

The value the `callback` function produced on its previous
        iteration. This concept is in the heart of reduce.

`currentValue`

This is the value of the current iteration, exactly same as in
        `map`.

`currentIndex`

The index. Just as in `map`.

`array`

The original array. Just as in `map`.

`initialValue`

A value to use as the first argument to the first call of the
    `callback`. If no `initialValue` is supplied, the
    first element in the array will be used as the initial accumulator value and
    skipped as `currentValue`.

## Reduce examples

Below are some examples to illustrate how it actually works.

### Summing up numbers in an array

The most basic example is to sum up all the values in an array:

```js
const coolNumbers = [69, 420, 666]

const holyNumber = coolNumbers.reduce((total, amount) => {
  return total + amount
})

console.log(holyNumber) // 1155 🔥
```

### Calculate an average

The formula for an average is: `sum of all the values` /
`total amount of items`.

Here’s the logic in English:

- Keep summing up the values `total += amount`.
- When hit the last item: divide the total with the item count.
- Return `total`.

```js
const moneys = [76.21, 420.69, 86.54]

const average = moneys.reduce((total, amount, index, array) => {
  total += amount
  const isLast = index === array.length - 1

  if (isLast) return total / array.length

  return total
})

console.log(average) // 194.48
```

This is a great example, because **it uses all four of the callback’s
arguments**.

### Returning an object

This is useful, and it is the only array method that can do this in JavaScript.
Here we need to use the second param of the reduce method, the `initialValue`.

Maybe we have a nested array structure of ISO-2 country codes and the country
names, and we’d like to turn it into an object where the country code is the
key, and country’s name the value.

- Pass in an empty object `{}` as the second parameter, this will be the value
  of the `accumulator` on the first run.
- The reduce method’s return value should be an object.
- The `accumulator` is spread at the end.

```js
const countries = [
  ['ch', 'Switzerland'],
  ['de', 'Germany'],
  ['fr', 'France'],
]

const regions = countries.reduce((acc, [countryCode, name]) => {
  return { [countryCode]: name, ...acc }
}, {})

console.log(regions)
// { fr: "France", de: "Germany", ch: "Switzerland" }
```

### Find and group same values in an array

With `reduce` it’s handy to find all occurrences of the same number from an
array:

```js
const numbers = [1, 1, 2, 3, 4, 4, 4, 5, 5, 5, 5]

const occurrences = numbers.reduce((accumulator, randomNumber) => {
  accumulator[randomNumber] = ++accumulator[randomNumber] || 1

  return accumulator
}, {})

console.log(occurrences)
// { '1': 2, '2': 1: '3': 1, '4': 3, '5': 4 }
```

This can be handy for example when you’re trying to visualize some data, or
figure out if a set of random numbers
[actually is random](/visualize-data-with-css#build-the-random-data).

## Conclusions

There’s a whole debate about whether we should use `reduce` at all. Some people
think it’s too nebulous, because everything that reduce can do can be done with
`for` loops.

I’ve embedded here a really nice episode of the **HTTP 203** podcast with the
topic of "Is reduce bad?" It’s worth the watch, there’s some nice nicknacks
there.

[YouTube](https://www.youtube.com/watch?v=qaGjS7-qWzg)

They reason that junior devs don’t use reduce because it’s complex, and properly
marinated seniors don’t use reduce because the pendulum has already swung into
its other apex.

Also, there’s a certain (false) purity with reduce and array methods that is
somehow appealing, by having one long, unbreakable chain where you process
things. When using `for` loops you need set the initial value into a separate
variable at first, which is totally fine, but there’s a weird... what do you
call it? kind of destructive, OCD driven, need for things to be concise and
neatly packaged.

Hope this was helpful. Thanks for reading.
