Skip to main content

JavaScript reduce() in depth

The reduce() method is an iterative method. It runs a reducer callback function over all elements in the array, in ascending-index order, and accumulates them into a single value.

// Syntax
reduce(callbackFn)
reduce(callbackFn, initialValue)
  • callbackFn : A function to execute for each element in the array. Its return value becomes the value of the accumulator parameter on the next invocation of callbackFn.
    • accumulator : The value resulting from the previous call to callbackFn. On the first call, its value is initialValue if the latter is specified; otherwise its value is array[0].
    • currentValue : The value of the current element. On the first call, its value is array[0] if initialValue is specified; otherwise its value is array[1].
    • currentIndex : The index position of currentValue in the array. On the first call, its value is 0 if initialValue is specified, otherwise 1.
    • array : The array reduce() was called upon.
  • initialValue - Optional : A value to which accumulator is initialized the first time the callback is called.

Working Logic:

How reduce() Work
const array = [15, 16, 17, 18, 19];

function reducer(accumulator, currentValue, index) {
const returns = accumulator + currentValue;
console.log(
`accumulator: ${accumulator}, currentValue: ${currentValue}, index: ${index}, returns: ${returns}`,
);
return returns;
}

array.reduce(reducer);

// Output
85

Basic reduction & techniques

const euros = [29.76, 41.85, 46.5];

const sum = euros.reduce((total, el) => total + el);

sum // 118.11
  • initialValue (say []) will become total in the first iteration.

Creating a Tally with the Reduce Method In JavaScript

We can use the below logic to find how many of each item are in the collection (Frequency of the item in an array).

const fruitBasket = ['banana', 'cherry', 'orange', 'apple', 'cherry', 'orange', 'apple', 'banana', 'cherry', 'orange', 'fig' ];
let max = 0;
let maxFruit = '';

const fruitsMap = fruitBasket.reduce( (tally, fruit) => {
tally[fruit] = (tally[fruit] || 0) + 1 ;
return tally;
} , {});

console.log(fruitsMap); // { banana: 2, cherry: 3, orange: 3, apple: 2, fig: 1 }

for(let fruit in fruitsMap) {
if(fruitsMap[fruit] > max) {
// `fruitsMap[fruit]` will return its count from map
max = fruitsMap[fruit];
maxFruit = fruit;
}
}

console.log(`${maxFruit} - ${max}`); // cherry - 3
  • tally[fruit] in line number 4 (Right side of =) is similar to tally.fruit, where tally is object (accumulator)
  • fruit is each elements of the array.

Break through of the above code:

  1. On our first pass, we want the name of the first key to be our current value(banana) and we want to give it a value of 1.
  2. This gives us an object with all the fruit as keys, each with a value of 1. We want the amount of each fruit to increase if they repeat.
  3. To do this, on our second loop we check if our total contain a key with the current fruit of the reducer. If it doesn’t then we create it. If it does then we increment the amount by one.

The above code in simplified form as below:

fruitBasket.reduce((tally, fruit) => {
if (!tally[fruit]) {
tally[fruit] = 1;
} else {
tally[fruit] = tally[fruit] + 1;
}
return tally;
}, {});

Character Frequency

Converting string into the object with letters & its frequency

const freqMap = str => str.split('').reduce(
(map, char) => (map[char] ??= 0, map[char]++, map),
{}
);

freqMap('anand');

// Output
{a: 2, n: 2, d: 1}

The ??= operator in JavaScript is the nullish coalescing assignment operator. It is a logical operator that returns its right-hand side operand when its left-hand side operand is null or undefined.

let x = null;
x ??= 5;
console.log(x); // 5

let y = undefined;
y ??= 10;
console.log(y); // 10

let z = 15;
z ??= 20;
console.log(z); // 15

We can see the explanation of the map. at line number 2.

(map[char] ??= 0, map[char]++, map)

This code is a concise way to increment the value associated with a key in a map. The ??= operator is called the nullish coalescing assignment operator. It checks if the value of map[char] is null or undefined. If it is, then the value of map[char] is set to 0. Otherwise, the value of map[char] is left unchanged.

The ++ operator increments the value of map[char]. The map variable is returned at the end of the expression.

Here is an example of how to use this code:

const map = new Map();

// Increment the value associated with the key 'a'
(map['a'] ??= 0, map['a']++, map);

// Increment the value associated with the key 'b'
(map['b'] ??= 0, map['b']++, map);

console.log(map); // { 'a': 1, 'b': 1 }

Flattening an array of arrays

const data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];

const flat = data.reduce((total, el) => {
return total.concat(el);
}, []);

flat // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
  • Each elements will be concatenated one after one. Our first pass is empty arrya. Then first element ([1, 2, 3]) will be be concatenated to empty array and so on.

reduceRight() method

The reduceRight() method works in the same way as the reduce() method, but in the opposite direction.

The reduce() method starts at the first element and travels toward the last, whereas the reduceRight() method starts at the last element and travels backward the first.

image