# Understanding Javascript .reduce() and its use cases

In this article, we’ll explore how the JavaScript Array `.reduce()`

method works, and some powerful use cases for it.

### First, what is it?

The reason I could never wrap my head around this method was failing to understand the word ‘reduce’, Oxford’s definition is:

To make smaller or less in amount, degree, or size.

This is exactly what the reduce function does. It iterates over an array (a group of elements of the *same type — ideally*) from left to right, and reduces it to a single value.

*Note: the single value could be an object or any primitive type.*

#### The easiest explanation

Imagine an array of numbers:

If we wanted to add all the numbers in the array, we could use a forEach loop:

The forEach method iterates from left to right, starting at 101.2 and adding it to 0; then over 242.2, adding it to 101.2 etc…

The reduce method equivalent, which doesn’t have the messy predefined variable spill over `let total = 0`

would be:

Here, the reduce method is applied to the `numbersToSum`

array, upon each iteration — we add the `currentNumber`

that’s being looped over to the `currentTotal`

(the current total defaults to 0 in the initial iteration — *sort of, explained later*).

This happens for every item in the `numbersToSum`

array, until our total is the sum of all the entries in the `numbersToSum `

array.

#### How it works

The reduce method takes in 2 parameters**.**

**First** — a callback function that accepts up to four parameters (all optional), namely the:

`previousValue`

: Whatever the previous iteration returned`currentValue`

: The current value in the array that’s being iterated over`currentIndex`

: The index of the current value`array`

: The array being iterated over

As the method iterates over the array elements, it allows you to manipulate the `previousValue`

that will be received by the next iteration. In other words, if we ran:

[1, 2, 3].reduce((previousValue, currentValue) => previousValue + currentValue)

For explanations sake: In the first iteration, we return `0 + 1`

, in the second iteration, our `previousValue`

now equals to 1, and we add it to 2 to alter the next `previousValue`

. In our last iteration our `previousValue`

is 3, we add it to our `currentValue`

of 3 and the reduce method returns a value of 6, the expected total.

The second parameter, following the 4-param callback, is the `initialValue`

, all this does is it sets the `previousValue`

used in the first iteration.

**The clever actuality:**

If you’ve worked with reduce a few times, you’ll know that the reduce function only iterates twice over the `[1, 2, 3]`

array. It does this for 2 clever reasons:

*First*, it reduces the iteration count. If it assumes `1`

as the `initialValue`

, this is the same as having the first iteration returning `0 + 1`

, so we can correctly skip the first, `0 + 1`

, iteration. The first iteration would then be looking at `2`

and adding an `initialValue`

of `1`

to it.

*Second* is typing; because the reduce function can return a single value of any type, assuming the type of element it’s working with using the first entry of the array makes its life easier. On it’s first iteration, if we’re adding an element to some initial value, if the values are not of the same type, it can get messy — see below:

0 + {} !== {} + 0

0 + {} // returns "0[object Object]"

{} + 0 // returns 0

If we were to initialise our reduce with an object instead, forcing 3 iterations:

[1, 2, 3].reduce((total, number) => total + number, {})

// it would return "[object Object]123"

// yuck

### When is it used?

If you were to reduce everyone’s use cases for the `reduce` function, it would be that:

The single use case for the `reduce` function is to create clusters of data.

### Use case examples

#### Single cluster: Sum of numbers in an array

[1, 2, 3].reduce((total, number) => total + number)

// returns 6

#### Single cluster: Averaging numbers in an array

[1, 2, 3].reduce((total, number, index, array) => {

total += number // add current number to total

if (index === array.length - 1) { // if we're at the last iter.

return total/array.length // return the average

}

return total

})

// returns 2 (= 6 / 3)

#### Single cluster: Flatten array

Say you had an array of blog articles, each containing an array of comments. If you wanted to get a list of all comments, you could use the reduce function:

#### Multiple clusters: Tally of items

Say we had an array of strings describing fruit:

If we wanted to return an object that would give us a tally of each fruit in the array (not knowing what fruit could possibly be in the array — hence we couldn’t use `.filter()`

)

We could simply write:

const fruitTally = fruit.reduce((currentTally, currentFruit) => {

currentTally[currentFruit] = (currentTally[currentFruit] || 0) + 1

return currentTally

} , {})

// returns {"apple":3,"banana":3,"cherry":2,"mango":2,"apricot":1,"guava":2}

#### Multiple clusters: Date categorisation

This is perhaps my favourite use case. Say you have a list of a users’ transactions with Unix timestamps and you wanted to group them by month (so a user could open one month, and close the others for better UX)

As it currently stands, the data is too flat to represent in any user friendly way, this could be an array of 1000 entries. We can categorise it neatly using a reducer:

### Conclusion

The `.reduce()`

function allows us to do some pretty neat data manipulation. It really shines when it comes to making data easier to work with, or easier to represent where it needs to be read by humans.