Notes

Array.reduce()

Edit on GitHub

JavaScript
4 minutes

.reduce()

The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value. MDN

  • The reduce() method reduces the array to a single value.
  • The reduce() method executes a provided function for each value of the array (from left-to-right).
  • The return value of the function is stored in an accumulator (result/total).
  • Note: reduce() does not execute the function for array elements without values.

use the reduce function on javascript arrays to transform a list of values into something else.

You need two things for .reduce()

  • a reducing function (reducer)
  • an accumulating value (accumulator)
  • an initial value (optional)

A reducer function takes an accumulator and return a new accumulator, by running every item in the array against the accumulator.

.reduce() always returns the final value of the accumulator. Remember, reducer function returns the accumulator. (i.e. Use the return in your functions)

In other words, the reducer function fires once for every item in the array and keeps accumulating the value to give a new value.

Examples

sum all the numbers

Here’s an example:

1const data = [3, 98, 16, 36, 13, 22, 46]
2
3let reducer = (accumulator, item) => accumulator + item
4
5let initialValue = 0
6
7let total = data.reduce(reducer, initialValue)
8
9console.info('total:', total) // total: 234

In the example above, we reduced an array to a final value (final accumulator), by adding the numbers in the data array, one by one to the accumulating value.

We started with an initial value (0), added it to the accumulator (3, first item of the data array) to get a new accumulator (0+3 = 3), then got to the next value (98), added that to the previous accumulator (3) to get a new accumulator (98+3 = 101), then got to the next value (16), added that to the previous accumulator (now 101) to get a new accumulator (16+101 = 117) and so on… till all items in the array were done and we ended with a final accumulator value of 234.

convert an array into an object

 1let votes = [
 2  'angular',
 3  'angular',
 4  'react',
 5  'ember',
 6  'react',
 7  'react',
 8  'vanilla'
 9]
10
11let initialValue = {}
12
13let reducer = (tally, vote) => { // tally is initialValue, vote is first item in votes array
14  if (!tally[vote]) { // if a key value doesn't exist
15    tally[vote] = 1
16  } else {
17    tally[vote] = tally[vote] + 1 // if a key value exists, increment it
18  }
19  return tally
20}
21
22let result = votes.reduce(reducer, initialValue)
23console.info(result) // { angular: 2, react: 3, ember: 1, vanilla: 1 }

reduce() vs. map() and filter()

.map() is a reducer function. So is .filter(). And they can be easily chained to create complex functions. But using reduce() can be faster than mapping and filtering when you have a lot of data. [^footnote] Here’s an example of the time difference between using map+filter vs. reduce

We’re going to get an array containing a million items, get all the even numbers in it, multiply them by two and get the resulting array.

1let bigData = []
2for (let i = 0; i < 1000000; i++) { 
3  bigData[i] = i // get an array containing a million numbers
4}
1console.time('bigData')
2
3let filterMappedData = bigData.filter(val => {
4   val % 2 === 0 
5 }).map(val => val*2)
6  
7console.timeEnd('bigData') // bigData: 44.423ms
 1console.time('bigDataReduced')
 2
 3let reducedData = bigData.reduce((acc, val) => {
 4  if (val % 2 === 0) {
 5    acc.push(val *2)
 6  }
 7  return acc
 8}, [])
 9
10console.timeEnd('bigDataReduced') // bigDataReduced: 68.954ms

i ran the example which accompanied the claim in the video 8 times, and reduce always took longer than map+filter

 1~/Sandbox $ node example.js
 2bigData: 44.423ms
 3bigDataReduced: 68.954ms
 4~/Sandbox $ node example.js
 5bigData: 44.178ms
 6bigDataReduced: 77.308ms
 7~/Sandbox $ node example.js
 8bigData: 34.717ms
 9bigDataReduced: 48.441ms
10~/Sandbox $ node example.js
11bigData: 43.447ms
12bigDataReduced: 61.104ms
13~/Sandbox $ node example.js
14bigData: 37.742ms
15bigDataReduced: 51.461ms
16~/Sandbox $ node example.js
17bigData: 34.192ms
18bigDataReduced: 46.665ms
19~/Sandbox $ node example.js
20bigData: 42.159ms
21bigDataReduced: 46.572ms
22~/Sandbox $ node example.js
23bigData: 31.489ms
24bigDataReduced: 51.182ms

Array.reduce => returns single value Array.map => returns new Array

Loop with memory. You need to provide it a reducer function

Accumulator = previous state = the last value you returned from the reducer function Current = current element in the loop

Start with many things and reduce it down to one thing

https://www.youtube.com/watch?v=tVCYa_bnITg


Related