Ways to use the Reduce method in Javascript
By: Cathy D
Tags: Recursion, JavaScript, Reduce, Higher Order Function, Reducer

Photo by Emile Perron on Unsplash

Until recently, I only knew how to use reduce for its most common purpose — to sum up all elements in an array. I knew it was capable of more, but only dove into its many uses when I started preparing for technical interviews.

It’s worth understanding the intricacies to use it to not only sum values, but to flatten arrays, sum the values in an array of objects, and even reverse a string.

Reduce, like map and filter, is a higher order function. A higher order function is a function that receives a function as an argument or returns the function as output. While map and filter are both fairly straightforward and intuitive, reduce is a little more complex. Every iteration is impacted by every previous iteration’s return value, and keeping track of the iterations in your head may take some practice — sort of like recursion.

How it works

The reduce method accepts two parameters: the reducer function (which is a callback) and an optional initial value. The reducer is executed on each member of the calling array, which results in a single output value.

To demonstrate this, let’s look at how to reduce without using the ‘reduce’ higher order function. It’s important to note that the reducer function that is passed in as a callback accepts 4 parameters: accumulator, currentValue, currentIndex, sourceArray. Below, the accumulator starts at its initial value (0) and is continually incremented by the element at each index.

let arr = [1,2,3,4,4,5]; //sourceArray let sum = 0; //initialValue, used to start accumulation for(let elem of arr){

sum = sum + elem; //accumulator + currentIndex (elem of array)

//0 + 1 - initial value plus elem

//1 + 2 - sum of previous iteration plus next elem in array

//3 + 3

//6 + 4

//10 + 4

//14 + 5

//19 - returns after last elem

} console.log(sum) //prints 19

Now understanding how the reducer callback works, we can simplify the process by using the reduce function. Here, we pass through an array and accumulate the same way, but a little bit cleaner. Here is another very cool animation that demos it out.

let sum = (arr) => {

return arr.reduce((accumulator, currentValue) => accumulator + currentValue, 0 //optional initialValue, defaults 0) //accumulator + currentValue (each elem of array)

//0 + 1 - initial value plus elem

//1 + 2 - sum of previous round plus next elem in array

//3 + 3

//6 + 4

//10 + 4

//14 + 5

//19 - returns after last elem } console.log(sum([1,2,3,4,4,5])) //prints 19

Other scenarios and uses

While reduce seems to be most commonly used to sum up the values in an array, it’s worth understanding in depth to use it in a variety of scenarios. Below are just a few examples of other ways to use reduce.

Create Objects

Counting the frequency of an element in an array is an important concept that comes up in a lot of algorithmic problems. While a ‘for loop’ is a perfectly fine brute force option, reduce could be a more elegant and potentially more efficient way of solving it.

Below, I use both a loop and reduce to count the frequency of letters in a string. This would also work with an array.

As a loop:

let str = 'banana';

let obj = {};

for (let char of str){

obj[char] ? obj[char] += 1 : obj[char] = 1

//if the key exists, increment its value by one; otherwise initiate key with a value of 1

} console.log(obj) // { b: 1, a: 3, n: 2 }

As reduce:

let str = 'banana';

const sumByChar = str.split('').reduce((acc, char) => ({

//use split to convert string to array of characters



...acc,

//using the spread operator on the accumulator will

give us access to all the properties in the object [char]: (acc[char] || 0) + 1,

// creating the element as a key - initializing to 1

if it does not exist, incrementing by 1 if it does }), {});

//initial value is an empty object console.log(sumByChar) // { b: 1, a: 3, n: 2 }

Reverse a string or array with reduce

The first time I was asked to reverse a string after bootcamp, I thought using the built-in reverse function was the obvious answer. I quickly learned that interviewers would likely not accept this as an answer. A loop seemed like the next obvious solution, and I soon learned that using reduce would be a more elegant option.

As a loop:

let str = '' for(let char of str){

str = char + str

//starts as empty string and accumulates one by one

//'' = h + ''

//h = e + h

//eh = l + eh

//leh = l + leh

//lleh = o + lleh

//olleh

} console.log('hello') // prints olleh

As reduce:

let reversed = (str) => str.split('').reduce((acc,char) => char + acc)

//accumulator starts empty and adds on one by one. if string, use .split('') to convert to array.

//'' = h + ''

//h = e + h

//eh = l + eh

//leh = l + leh

//lleh = o + lleh

//olleh console.log(reversed('hello')) // prints olleh

Flatten an array

When you have an arrays within an array for whatever reason, you may want to combine them into one ‘flattened’ array. Again, while there is the built in ‘flat’ method you can usually use, in an interview you may not be able to use that built in function. Reduce can solve this with recursion. This one was a bit of a doozy for me, but I promise it’s good practice for both reduce and recursion!

let flattenArray = (arr) => {

return arr.reduce((total, curr) => {

return total.concat(Array.isArray(curr) ? flattenArray(curr) : curr);



//if the value is an array, the recursively call reduce until next nested array

//if the value is not an array, then just concatenate the value to the flattened array.



//total [] curr 2

//total [ 2 ] curr 1

//total [ 2, 1 ] curr [ 3, 10, [ 12 ] ]

//total [] curr 3

//total [ 3 ] curr 10

//total [ 3, 10 ] curr [ 12 ]

//total [] curr 12



//returns [ 2, 1, 3, 10, 12 ] }, []);

//initial value is an empty array } console.log(flattenArray([2, 1, [3, 10, [12]]]))

// returns [2, 1, 3, 10, 12]

I hope that these breakdowns and examples help you understand how reduce works and how to implement it beyond summing up values!

Resources

https://eloquentjavascript.net/05_higher_order.html

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

https://blog.bitsrc.io/understanding-higher-order-functions-in-javascript-75461803bad

https://blog.khanacademy.org/lets-reduce-a-gentle-introduction-to-javascripts-reduce-method/

https://medium.com/@vmarchesin/using-array-prototype-reduce-in-objects-using-javascript-dfcdae538fc8

https://www.digitalocean.com/community/tutorials/js-finally-understand-reduce#flattening-an-array-using-reduce