.reduce() Method

  • Array Method
  • Array Methods
  • Code
  • JavaScript

Most likely the primary example everyone sees when they are first exposed to the .reduce() method is its use in finding the sum of an array of numbers. The following operation yields 10:

[0, 1, 2, 3, 4].reduce(function (  accumulator,  currentValue,  currentIndex,  array) {  return accumulator + currentValue;});

The .reduce() method takes a callback function and an initial value (optional). The callback function has four available parameters:

  • accumulator
  • currentValue
  • currentIndex (optional)
  • array (optional)

The structure, including all optional pieces, would be:

const sum = [0, 1, 2, 3, 4].reduce(function (  accumulator,  currentValue,  currentIndex,  array) {  return accumulator + currentValue;},initialValue);

What threw me for a loop when I first started seeing this syntax was the accumulator. In our first example, there is no initialValue passed, so where does the accumulator know where to start? The answer, according to MDN: If no initialValue is provided, then accumulator will be equal to the first value in the array, and currentValue will be equal to the second.

Walk through it

So let's break down what's happening at each step in the first example.

First Call

ParameterValue
accumulator0
currentValue1
currentIndex1
array[0, 1, 2, 3, 4]
returnValue1

Second Call

ParameterValue
accumulator1
currentValue2
currentIndex2
array[0, 1, 2, 3, 4]
returnValue3

Third Call

ParameterValue
accumulator3
currentValue3
currentIndex3
array[0, 1, 2, 3, 4]
returnValue6

Fourth Call

ParameterValue
accumulator6
currentValue4
currentIndex4
array[0, 1, 2, 3, 4]
returnValue10

That starts to clear things up.

With an initialValue

Now let's see how it works when we pass in the optional initial value:

[0, 1, 2, 3, 4].reduce(function (  accumulator,  currentValue,  currentIndex,  array) {  return accumulator + currentValue;},30);

First Call

ParameterValue
accumulator30
currentValue0
currentIndex0
array[0, 1, 2, 3, 4]
returnValue30

Second Call

ParameterValue
accumulator30
currentValue1
currentIndex1
array[0, 1, 2, 3, 4]
returnValue31

Third Call

ParameterValue
accumulator31
currentValue2
currentIndex2
array[0, 1, 2, 3, 4]
returnValue33

Fourth Call

ParameterValue
accumulator33
currentValue3
currentIndex3
array[0, 1, 2, 3, 4]
returnValue36

Fifth Call

ParameterValue
accumulator36
currentValue4
currentIndex4
array[0, 1, 2, 3, 4]
returnValue40

currentIndex and array Arguments

The currentIndex and array arguments also prove useful when we want to calculate an average:

const array = [10, 20, 33, 40, 50];const average = array.reduce(function (  accumulator,  currentValue,  currentIndex,  array) {  accumulator += currentValue;  if (currentIndex === array.length - 1) {    return accumulator / array.length;  } else {    return accumulator;  }});

First Call

ParameterValue
accumulator10
currentValue20
currentIndex1
array[10, 20, 33, 40, 50]
returnValue30

Second Call

ParameterValue
accumulator30
currentValue33
currentIndex2
array[10, 20, 33, 40, 50]
returnValue63

Third Call

ParameterValue
accumulator63
currentValue40
currentIndex3
array[10, 20, 33, 40, 50]
returnValue103

Fourth Call

ParameterValue
accumulator103
currentValue50
currentIndex4
array[10, 20, 33, 40, 50]
returnValue30.6

Beyond Math

.reduce() can be used for far more than math operations. When you start including empty objects or arrays as the initial value, the true extensibility of this method starts shining through.

For example, let's take a tally of the number of times each vehicle is listed in this array:

const cars = [  "toyota",  "chevrolet",  "ford",  "toyota",  "mitsubishi",  "toyota",  "chevrolet",  "toyota",  "ford",  "kia",  "toyota",];
const tally = cars.reduce(function (  accumulator,  currentValue,  currentIndex,  array) {  accumulator[currentValue] = (accumulator[currentValue] || 0) + 1;  return accumulator;},{});
console.log(tally);

Or, let's figure out how many times each word is listed in a paragraph.

const paragraph =  "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?";
const dictionary = paragraph  .replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "")  .split(" ")  .reduce((tally, currentWord) => {    tally[currentWord] = (tally[currentWord] || 0) + 1;    return tally;  }, {});

This is, of course, a very rough example using some RegEx that I found online and haven't fully vetted, but it illustrates both how .reduce() can be chained onto other methods and how an empty object passed in as the initialValue can be a powerful thing.

The last example I want to give for this method (which I can still do to read more about and use more often) is an exercise from Marijn Haverbeke's Eloquent JavaScript:

Use the .reduce() method in combination with the .concat() method to "flatten" an array of arrays into a single array that has all the elements of the input arrays.

const arrayOfArrays = [  [1, 2],  [3, 4],  [5, 6],];const flattened = arrayOfArrays.reduce(  (flat, currentElement) => flat.concat(currentElement),  []);console.log(flattened);// expected result: [1, 2, 3, 4, 5, 6];

From MDN: The .reduce() method executes a reducer function (that you provide) on each element of the array, resulting in a single output value.

See more examples and further documentation here.