How to use reduce in javascript
Tags: reduce, javascript, typescript, aggregate
Published: 2020-12-16 13:49:33

---
title: How to use reduce in javascript
published: true
description: 
tags: reduce, javascript, typescript, aggregate
//cover_image: https://direct_url_to_image.jpg
---
# How to use `reduce` in javascript

Reduce is one of those functions that seems to get a [marmite](https://www.youtube.com/watch?v=9XvD4ytLkJw) reaction. Some people love it, and others hate it. 
I'm primarily a .NET developer and am a big fan of [LINQ](https://en.wikipedia.org/wiki/Language_Integrated_Query) when it comes to collections. The two most commonly used methods from this library are likely to be `Select` and `Where`, which in JavaScript correspond to `map` and `filter`, and are used in pretty much the same way.

```csharp
const values = [1, 2, 3, 4]
var doubled = values.Select(x => 2*x); // returns [2, 4, 6, 8]
var odds = values.Where(X => x % 2 != 0); // returns [1, 3]
```

```javascript
const values = [1, 2, 3, 4]
const doubled = values.map(x => 2*x) // returns [2, 4, 6, 8]
const odds = values.filter(x => x % 2 !== 0) // returns [1, 3]
```

But when I first came across reduce I realised I didn't know what the LINQ equivalent was. It's `Aggregate` btw, but the reason I didn't know is because I had simply never needed it. This isn't because this type of function is useless, but because LINQ provides a host of other more specific aggregate functions, especially if you also use [MoreLINQ](https://github.com/morelinq/MoreLINQ) as we do.

## Useful Aggregates

The sort of aggregate functions I immediately started to use reduce for were things like `Sum`, `Min`, `Max`, `Distinct`, etc.

The same result can usually be achieved by using a `forEach` loop and there's no reason why you can't. My preference for using reduce is that the code often looks very similar, but is still a pure function that doesn't rely on mutable variables.

### Sum

Consider these approaches to adding an array of numbers using `forEach` and `reduce` (there will be a full explanation of the code in the next section).

#### `forEach`
```javascript
let total = 0;
values.forEach(x => {
    total += x
})
```

#### `reduce`
```javascript
const total = values.reduce((prev, curr) => {
    return prev + curr
}, 0)
```

The `forEach` depends on a variable value which can be changed, and wraps this in a closure allowing it to be progressively added to, where the `reduce` implementation is a pure function the result of which goes directly in to an immutable constant.

## Reduce

The `reduce` function takes in two arguments
* The reducer
* An optional initial value

The reducer is the part that confuses most people. The reducer is a function that will perform the aggregation one value at a time. If you've seen the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) then you know that the reducer can accept up to 4 parameters, but typically you only need the first two. I always call these two parameters `prev`, and `curr`. It's worth noting though that `prev` is not the previous value in the array but the previous value returned by the reducer. Continuing with summing as an example:

### Sum

```javascript
const values = [1, 2, 3, 4]
const reducer = (prev, curr) => {
    return prev + curr
}
const total = values.reduce(reducer, 0)
```

I've extracted the reducer into a separate variable just to make it clearer which part of the above I'm talking about. This reducer function will be called once for each value in the array.

The first time we come in `prev` takes the value of the second parameter passed to `reduce`, in this case `0` (If we didn't specify an initial value it would be `undefined`). `curr` would be the first value from the array. It adds the two and returns the result. The next time the reducer is called this result will become the `prev` value. See the table below for what happens to each parameter is it loops through the array.

| Loop # | `prev` value | `curr` value | Returned value |
| ------ | ------------ | ------------ | -------------- |
| 1      | 0            | 1            | 1              |
| 2      | 1            | 2            | 3              |
| 3      | 3            | 3            | 6              |
| 4      | 6            | 4            | 10             |

The final result `10` would be returned from the `reduce` function and stored in the `total` constant.

### Max

Another example, this time we'll find the greatest number in an array of numbers.

```javascript
const values = [15, 6, 12, 24, 3, 11]
const max = values.reduce((prev, curr) => {
    return prev > curr ? prev : curr
})
```

This time our table of values will look like:

| Loop # | `prev` value | `curr` value | Returned value |
| ------ | ------------ | ------------ | -------------- |
| 1      | `undefined`  | 15           | 15             |
| 2      | 15           | 6            | 15             |
| 3      | 15           | 12           | 15             |
| 4      | 15           | 24           | 24             |
| 5      | 24           | 3            | 24             |
| 6      | 24           | 11           | 24             |

With `24` as our final result.

## Aggregates with different types to the array

So far the return type of our reducer has been the same as the input types, which means that both `prev` and `curr` parameters have also been of the same type, but this is not always the case.

In this example we'll convert an array of objects into a javascript object. This can be useful for using it as a dictionary.

```javascript
const values = [
    {id: 106, name: "Wibble"},
    {id: 357, name: "Wobble"},
    {id: 652, name: "Flibble"}
]

const valuesDictionary = values.reduce((prev, curr) => {
    return {
        ...prev,
        [curr.id]: curr
    }
}, {})

console.log(valuesDictionary[652]) // outputs "{id: 652, name: "Flibble"}"
```

This example makes use of the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) to take the properties of the `prev` parameter and add them all to the new object the reducer returns. The end result is a JS object which you can use as a dictionary to look up each item by its id.

The above achieves the same result as .NET's `ToDictionary` method.