3 Simple Snippets to Help You Understand Array .reduce()! 🥳  
Tags: javascript, node, tutorial, webdev
Published: 2020-02-04 14:05:21

---
title: 3 Simple Snippets to Help You Understand Array .reduce()! 🥳  
published: true
description: 
tags: javascript, node, tutorial, webdev
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/9alg3ed1cs73d8y0d413.png
---

*If you find this post useful, you can follow me on [twitter](https://twitter.com/_twosmalltrees), sign up to my [mailing list](https://www.twosmalltrees.com/mailing-list) or check out the other posts on my [blog](https://www.twosmalltrees.com). I've also got a couple of active side projects that you might like to check out:*

* *[ippy.io](https://www.ippy.io) - An app for creating beautiful resumes*
* *[many.tools](https://many.tools) - A collection of useful utilities for designers and devs*

<hr />

Are you having trouble getting your head around the JS Array `.reduce()` method? 

If so, don't worry - you're not alone. For whatever reason, the reduce method seems to take a while to click for many developers. I've been in this boat myself. Fortunately, once you break things down, it's not too complex. 

My aims for this article are to: 

1. Offer what I think is a useful mental model for thinking about `.reduce()`.
2. Provide a series of usage examples to strengthen your understanding

Let's get started.


## The Mental Model

Reduce is often introduced as a way of *reducing* an array to a single value. While this is indeed what it does, I've never found this to be particularly helpful in understanding how it works, or what I might be able to do with it.

For me, the simplest way to think about `.reduce()` is as a fancy case of `.forEach()`. The essentials are similar:

* We provide a callback function 
* We iterate over the array, and execute the callback function once per array item.

The important differences are that with `.reduce()`:

* Each invocation of the callback is aware of the return value of the previous invocation (or on the first call, the initial value we've provided). 
* Once there are no more items in the array, the return value of the last callback invocation is returned as the final result of the `.reduce()` call.

In fact, we can implement a reduce function ourselves using a slim wrapper around `.forEach()`:

```javascript

const reduce = (array, callback, initialValue) => {
  // Originally stores the initialValue then updated
  // on each iteration with the return value of the callback.
  let previousReturnValue = initialValue

  // Iterate over the array items, updating the currentReturn value at each step.
  array.forEach((item, index) => {
    const result = callback(previousReturnValue, item, index, array)
    previousReturnValue = result;
  })

  // Return the final value once all array items have been iterated over
  return previousReturnValue
}

```

<hr />

Let's now look at some examples of using `.reduce()`, and step through the execution path.

## 1. Adding an array of numbers

In this common example, we're adding an array of numbers to arrive at a final sum:

```javascript

const initialValue = 0

const numbersToAdd = [ 1, 2, 3, 4 ]

const addFunction = (runningTotal, numberToAdd) => {
  return runningTotal + numberToAdd;
}

const sum = numbersToAdd.reduce(addFunction, initialValue)

console.log(sum)
// => 10

// =======================================================

// How was this calculated? Lets step through it:

// The addFunction callback is invoked for each array item:

// -- FIRST CALLBACK INVOCATION -- 
// Array Item => 1
// Previous return value => first invocation (so the initialValue is used)
// Callback invocation => numbersToAdd(0, 1)
// Callback return value => 1

// -- SECOND CALLBACK INVOCATION --
// Array Item => 2
// Previous return value => 1
// Callback invocation => numbersToAdd(1, 2)
// Callback return value => 3

// -- THIRD CALLBACK INVOCATION --
// Array Item => 3
// Previous return value => 3
// Callback invocation => numbersToAdd(3, 3)
// Callback return value => 6

// -- FOURTH (AND LAST) CALLBACK INVOCATION --
// Array Item => 4
// Previous return value => 6
// Callback invocation => numbersToAdd(6, 4)
// Callback return value => 10

// Final Result: 10

```
<hr />

## 2. Finding the largest of an array of numbers

Here we'll use reduce to find the maximum value in an array. 

This is a slightly special case, in that we haven't provided `.reduce()` with an initial value argument. Because of this, `.reduce()` skips the callback for the first array item, and instead uses it as the initial value for the callback invocation on the second array item.

```javascript

const numbers = [ 10, 40, 4, 50, 101 ]

const findLarger = (currentMax, numberToCheck) => {
  if (numberToCheck > currentMax) {
    return numberToCheck;
  }
  return currentMax;
}

const largest = numbers.reduce(findLarger)

console.log(largest)
// => 101

// =======================================================

// How was this calculated? Lets step through it:

// The findLarger callback is invoked for each array item:

// -- FIRST CALLBACK INVOCATION -- 
// Array Item => 10
// Previous return value => first invocation, and no initialValue provided
// Callback invocation => Not Invoked
// Callback return value => N/A

// -- SECOND CALLBACK INVOCATION --
// Array Item => 40
// Previous return value => nothing, however first array item will be used as the initialValue
// Callback invocation => findLarger(10, 40)
// Callback return value => 40

// -- THIRD CALLBACK INVOCATION --
// Array Item => 4
// Previous return value => 40
// Callback invocation => findLarger(40, 4)
// Callback return value => 40

// -- FOURTH CALLBACK INVOCATION --
// Array Item => 50
// Previous return value => 40
// Callback invocation => findLarger(40, 50)
// Callback return value => 50

// -- FIFTH (AND LAST) CALLBACK INVOCATION --
// Array Item => 101
// Previous return value => 50
// Callback invocation => findLarger(50, 101)
// Callback return value => 101

// Final Result: 101

```

<hr />

## 3. Categorising an array into even/odd numbers.

Of course, you're not restricted to returning numbers from the callback in `.reduce()`. You can return anything you want. In this case, we return an object that is categorising the array values into even/odd buckets.

```javascript

const initialValue = { even: [], odd: [] }

const numbersToCategorise = [1, 3, 4, 8, 10]

const categorisingReducer = (categories, numberToCategorise) => {
  const isEven = numberToCategorise % 2 === 0
  if (isEven) {
    categories.even.push(numberToCategorise)
  } else {
    categories.odd.push(numberToCategorise)
  }
  return categories
}

const categories = numbersToCategorise.reduce(categorisingReducer, initialValue)

console.log(categories)

//  => { even: [4, 8, 10], odd: [1, 3] }

// =======================================================

// How was this calculated? Again, lets step through it:

// The categorisingReducer callback is invoked for each array item:

// -- FIRST CALLBACK INVOCATION -- 
// Array Item => 1
// Previous return value => first invocation (so the initialValue is used)
// Callback invocation => categorisingReducer({ even: [], odd: [] }, 1)
// Callback return value => { even: [], odd: [1] }

// -- SECOND CALLBACK INVOCATION --
// Array Item => 3
// Previous return value => { even: [], odd: [1] }
// Callback invocation => categorisingReducer({ even: [], odd: [1] }, 3)
// Callback return value => { even: [], odd: [1, 3] }

// -- THIRD CALLBACK INVOCATION --
// Array Item => 4
// Previous return value => { even: [], odd: [1, 3] }
// Callback invocation => categorisingReducer({ even: [], odd: [1, 3] }, 4)
// Callback return value => { even: [4], odd: [1, 3] }

// -- FOURTH CALLBACK INVOCATION --
// Array Item => 8
// Previous return value => { even: [4], odd: [1, 3] }
// Callback invocation => categorisingReducer({ even: [4], odd: [1, 3] }, 8)
// Callback return value => { even: [4, 8], odd: [1, 3] }

// -- FIFTH (AND LAST) CALLBACK INVOCATION --
// Array Item => 10
// Previous return value => { even: [4, 8], odd: [1, 3] }
// Callback invocation => categorisingReducer({ even: [4, 8], odd: [1, 3] }, 10)
// Callback return value => { even: [4, 8, 10], odd: [1, 3] }

// Final Result: { even: [4, 8, 10], odd: [1, 3] }
```

<hr />

Let me know in the comments if this was useful, or if anything about the `.reduce()` method is still unclear to you!