A guide to using the JavaScript reduce array method

A guide to using the JavaScript reduce array method

The JavaScript reduce method is one of the methods used in functional programming and can be quite hard to understand. In this article, we will explore how it works and take a look at some examples.

The Reduce Method: What is it?

The reduce method executes a callback function on every element of an array, from left to right, and returns a single output value. The syntax is as follows:

array.reduce(callback(accumulator, currentValue, currentIndex, arr), initialValue);

or rather,

array.reduce(callback, initialValue);

Remember, the callback is the function that will be called upon every single element of an array, and it takes in four arguments as shown above and described below.

  • The accumulator accumulates the returned value of the callback function. It is a required parameter.

  • The currentValue is the value of the current element being processed in the array. It is a required parameter.

  • The currentIndex is the array index of the current element being processed in the array. It is an optional parameter.

  • The arr is the array object the current element belongs to. It is an optional parameter.

The initialValue is the value of the first argument to the first call of the callback function. If no initialValue is provided, the first element in the array will be used as the initial accumulator value. Therefore, the initial callback function will start at index 1, not index 0 of the array. It is thus safer to provide an initialValue, and should be one of the first things to check out for when debugging.

Don't worry if the syntax seems a little confusing. We will dive deeper into the workings of the reduce method using a couple of examples.

Let's take a look at some examples now, shall we?

1. Sum of array elements

Let's take a look at a classic example of how one can sum up elements of an array using the for loop:

let results = 0;

const arrayNumbers = [10,20,30];

for(let num=0; num<arrayNumbers.length; num++){
    results += arrayNumbers[num];
}

console.log(results); //results = 60

This can also be done using the reduce method without mutating the results variable as shown below:

//initial value or starting point of the callback function
const initialValue = 0;

//array of numbers
const arrayNumbers = [10,20,30];

//the reduce method takes in the sum function as the callback function and the initialValue
const results = arrayNumbers.reduce(sum, initialValue);

//the sum function 
function sum(accumulator, currentValue){
      return accumulator + currentValue;
}

console.log(results); //results = 60

The explanation for the above code is as follows:

  • The first time the callback function is called, the accumulator will be equal to the initialValue which is 0.

  • On each call to the function, the currentValue is added to the accumulator, for example 10 is added to the accumulator, thus accumulator equals 10, and the calculation is repeated for each element on the array, with the currentValue changing to the next number in the array.

  • When there are no more numbers left in the array, the method returns the accumulator value of the last callback invocation, which is 60.

This can also be written using an arrow function as shown below:

const arrayNumbers = [10,20,30];

const results = arrayNumbers.reduce((accumulator, currentValue) => {
       return accumulator + currentValue;
}, 0);

console.log(results) //results = 60

Pretty cool, right? Let's check out other ways to use the reduce method.

2. Find the maximum element in a numeric array

The reduce method here works by comparing each value to find the maximum element of an array. This method has its pros over using apply and the spread(...) operator, which may fail or return a wrong result if the array has too many elements.

const arr = [1,5,25,13,55];

const largestNum = arr.reduce((accumulator,value) => {
      if(accumulator> value){
           return accumulator;
      } else {
           return value;
      }
}, []);

console.log(largestNum);  //returns 55

The Math.max() function can also be used in place of an if statement to return the largest number.

const arr = [1,5,25,13,55];

const largestNum = arr.reduce((accumulator,value) => {
        return Math.max(accumulator,value);
}, []);

console.log(largestNum);  //returns 55

3. Sum values in an object array

The reduce method can be used to sum up values contained in an array of objects. However, an initialValue must be provided to avoid running into an error.

Let's say we have an object property of shoppingList, and we need to get the total cost of the products.

const shoppingList = [
    {
        product: 'eggs',
        price: 10,
        numberOfItems: 30
    },
    {
        product: 'bananas',
        price: 5,
        numberOfItems: 10
    },
    {
        product: 'cups',
        price: 20,
        numberOfItems: 15
    }
];

Using the reduce method, we can get the total or accumulated value of the products, whose price and numberOfItems values can be accessed using the dot notation.

const totalCost = shoppingList.reduce((accumulator, item) => {
    return accumulator + (item.price * item.numberOfItems);
}, 0);

console.log(totalCost); //returns 650

4. Flatten an array

The reduce method can also be used to flatten a nested array in place of the .flat method.

const data = [[15,25], [30,50], 3];

In the example below, we set the initial value to an empty array and concatenate the val to the acc.

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

console.log(flat); //return [15, 25, 30, 50, 3]

Let's go through another example, where arrays can be nested in more complicated ways such as shown below:

const flowers = [
    {
        name: 'rose',
        color: ['red', 'yellow', 'white', 'pink', 'orange']
    },
    {
        name: 'dahlia',
        color: ['orange', 'pink', 'white', 'lavender', 'red']
    },
    {
        name: 'morning glory',
        color: ['purple', 'blue', 'red', 'white', 'pink']
    }
];

We can access the colors from each object using the dot notation on the cur argument. We can then use the forEach() method to push every value that lies in the color property to acc.

const allColors = flowers.reduce((acc,cur) => {
    cur.color.forEach(col => acc.push(col) )
    return acc;
}, []);

This results in a single array that contains all the color values. However, this array has multiple repeat elements, which we can fix using an if statement and indexOf(), which will check if an element exists in acc or not and will update accordingly.

const allColors = flowers.reduce((acc,cur) => {
    cur.color.forEach(col => {
        if(acc.indexOf(col) === -1){
            acc.push(col);
        }
    })
    return acc;
}, []);

Which thus leads to a single array that has only one occurrence of an element.

["red", "yellow", "white", "pink", "orange", "lavender", "purple", "blue"]

5. Counting instances of an object

The reduce method can also be used to sum up the instances of values in an object.

Let's say we have an array such as this:

const colors = ['green', 'blue', 'purple', 'red', 'blue', 'purple', 'purple'];

To find the instances of a value appearing in the array, we can use an if statement to count the number of times a color appears in acc. If a color appears more than once, we add up the number of times and return the total number of times the color appears, else we return 1 for the colors that only appear once.

const countColors = colors.reduce((acc, color) => {
    if(color in acc){
        acc[color]++
    } else {
        acc[color] = 1;
    }
    return acc;
}, []);

The result will thus be:

[green: 1, blue: 2, purple: 3, red: 1]

Conclusion

The reduce method can seem to be more complex compared to other JavaScript methods. Having a clear understanding of the syntax, the core concepts as well as some of the cases in which the method is used can be of much help and can be a powerful tool in data manipulation.