How the `reduce()` method is different from the `map()`, `filter()`, and `find()` method?

How the `reduce()` method is different from the `map()`, `filter()`, and `find()` method?

In this article, I will explain an array method which intimidates people who are beginners in JavaScript i.e., reduce() method. If we compare the arguments of callback function of reduce() method with other frequently used array methods like map(), filter(), find() method then we will find that there is an extra argument present in the reduce() method which is accumulator. Let's try to understand this difference by some examples. I will explain all four methods using a different problem statement.

Let's start with the reduce() method. Here, the problem statement is to find the sum of all elements of the given array.

The reduce() method executes a callback function on each element of the array, in order, passing in the return value from the calculation on the preceding element. The final result will be a single value.

There are two possible cases. First one, when initialValue is provided and second one, when initialValue is not provided. To elaborate these cases, I will use three different approaches which all give the same result but their way of representation will be different from each other. In the first approach, I will use a 'Named Function' as an argument. In the second approach, I will use an 'Anonymous Function' as an argument. In the third approach, I will use shorthand syntax in an 'Anonymous Function'.

// PROBLEM STATEMENT: Find the sum of all elements of the given array
// CASE 1: When `initialValue` is provided
// APPROACH 1: Passing a 'Named Function' to reduce() method as first argument

const numbers = [2, 5, 8]

const addNumbers = (previousResult, currentItem, currentIndex, array) => {
  console.log({ previousResult, currentItem, currentIndex, array })
  return previousResult + currentItem
}

const initialValue = 0

const total = numbers.reduce(addNumbers, initialValue)

console.log(total) 

//Output: 
// {previousResult: 0, currentItem: 2, currentIndex: 0, array: [2, 5, 8]}
// {previousResult: 2, currentItem: 5, currentIndex: 1, array: [2, 5, 8]}
// {previousResult: 7, currentItem: 8, currentIndex: 2, array: [2, 5, 8]}
// 15

In the above example, we have an array i.e., numbers. We are applying the reduce() method on the array in order to find the sum of all elements of the array which basically reduce the array in one number. Here, we passed two parameters namely callback function and initialValue to reduce() method.

Now, let's closely look at the callback function i.e., addNumbers. We can pass four arguments in the callback function viz. accumulator, currentValue, currentIndex and array. For better understanding , I used previousResult and currentItem instead of accumulator and currentValue respectively in the above example. The name of the arguments are up to you. They are user specified. I used currentIndex and array for showing them on the console. There is no use of these two arguments in the calculation. For clearer comprehension, I used a log statement, so that we can see execution of the callback function on each element of the array. Lastly, in the return statement, I add the previousResult and currentItem in order to get the sum of all elements of the array.

Now, let's move to the second parameter of reduce() method i.e., initialValue which is optional. If we do not provide the second parameter to the reduce() method then the array element at index 0 is used as the initial value and iteration starts from the next element (index 1 instead of index 0).

// CASE 2: When `initialValue` is NOT provided
// APPROACH 1: Passing a 'Named Function' to reduce() method as first argument

const numbers = [2, 5, 8]

const addNumbers = (previousResult, currentItem, currentIndex, array) => {
  console.log({ previousResult, currentItem, currentIndex, array })
  return previousResult + currentItem
}

const total = numbers.reduce(addNumbers)

console.log(total) 
//Output: 
// {previousResult: 2, currentItem: 5, currentIndex: 1, array: [2, 5, 8]}
// {previousResult: 7, currentItem: 8, currentIndex: 2, array: [2, 5, 8]}
// 15

The second approach will be using an anonymous Function to reduce() method as argument instead of using a named function like we used in our first approach. Here, I will not use currentIndex and array as arguments in the callback function because there is no use of these arguments in the calculation.

Firstly, we will see the first case where we are providing the initialValue. Here, I will directly pass the initialValue as the second parameter of the reduce method without storing it in a variable for shortening the code.

// CASE 1: When `initialValue` is provided
// APPROACH 2: Passing an 'Anonymous Function' to reduce() method as first argument

const numbers = [2, 5, 8]

const total = numbers.reduce((previousResult, currentItem) => {
  console.log({ previousResult, currentItem })
  return previousResult + currentItem
}, 0)

console.log(total)
//Output: 
// {previousResult: 0, currentItem: 2}
// {previousResult: 2, currentItem: 5}
// {previousResult: 7, currentItem: 8}
// 15

We can even shorten the above code by deleting the log statement. So, after deleting the log statement there will be only one line return statement left. So, we can remove the return keyword.

// CASE 1: When `initialValue` is provided
// APPROACH 3: Passing an 'Anonymous Function' to reduce() method as first argument [Using shorthand syntax]

const numbers = [2, 5, 8]

const total = numbers.reduce((previousResult, currentItem) => previousResult + currentItem, 0)

console.log(total) //Output: 15

Similarly, we can write the code of the second case where we are not providing the initialValue. I will not show the second approach of the case second in order to reduce the length of the article.

// CASE 2: When `initialValue` NOT is provided
// APPROACH 3: Passing an 'Anonymous Function' to reduce() method as first argument [Using shorthand syntax]

const numbers = [2, 5, 8]

const total = numbers.reduce((previousResult, currentItem) => previousResult + currentItem)

console.log(total) //Output: 15

Now, let's see how to pass the arguments in the callback function of map() method, filter() method, and find() method. There are three arguments that we pass to these methods namely element, index, and array. The difference between these three methods and the reduce() method is the accumulator argument. The callback function of reduce() method has an extra argument i.e., accumulator which is the value resulting from the previous call to callback function. On the first call, its value is initialValue if the latter is specified; otherwise its value is array[0].

A table showing the difference between  method and other repeatedly used methods like , ,  method

I will start with the map() method. I will explain this method using a problem statement. The problem statement is to add 1 to all the elements of the given array.

// `map()` method
// PROBLEM STATEMENT: Add `1` in all elements of the given array

const numbers = [97, 98, 99];
console.log(`Original given array is: [ ${numbers} ]`)

const addOne = numbers.map((number, index, array) => {
  console.log({ number, index, array })
  return number + 1
}, 0)

console.log(`Final result array is: [ ${addOne} ]`)
console.log(`Original given array after applying map() method is: [ ${numbers} ]`)

//Output: 
// Original given array is: [ 97,98,99 ]
// { number: 97, index: 0, array: [ 97, 98, 99 ] }
// { number: 98, index: 1, array: [ 97, 98, 99 ] }
// { number: 99, index: 2, array: [ 97, 98, 99 ] }
// Final result array is: [ 98,99,100 ]
// Original given array after applying map() method is: [ 97,98,99 ]

In this code, the first argument of the callback function is number. Here, number is the current element being processed in the array, index is the index of the current element being processed in the array, and array is the array on which the map() method was called.

The map() method created a new array (i.e., [ 98, 99, 100 ]) populated with the results of calling the callback function on every element in the calling array (i.e., [ 97, 98, 99 ]).

Now, moving towards the filter() method. Here, the problem statement is to find all the numbers which are even in the given array.

// `filter()` method 
// PROBLEM STATEMENT: Find all the numbers which are even in the given array

const numbers = [1, 2, 3, 4, 5, 6]
console.log(`Original given array is: [ ${numbers} ]`)

const filterEvenNumbers = numbers.filter((number, index, array) => {
  console.log({ number, index, array })
  return number % 2 == 0
})

console.log(`Final result array is: [ ${filterEvenNumbers} ]`)
console.log(`Original given array after applying filter() method is: [ ${numbers} ]`)

// Output:
// Original given array is: [ 1,2,3,4,5,6 ]
// { number: 1, index: 0, array: [ 1, 2, 3, 4, 5, 6 ] }
// { number: 2, index: 1, array: [ 1, 2, 3, 4, 5, 6 ] }
// { number: 3, index: 2, array: [ 1, 2, 3, 4, 5, 6 ] }
// { number: 4, index: 3, array: [ 1, 2, 3, 4, 5, 6 ] }
// { number: 5, index: 4, array: [ 1, 2, 3, 4, 5, 6 ] }
// { number: 6, index: 5, array: [ 1, 2, 3, 4, 5, 6 ] }
// Final result array is: [ 2,4,6 ]
// Original given array after applying filter() method is: [ 1,2,3,4,5,6 ]

In this code, the filter() method created a shallow copy of a portion of a given array (i.e., [1, 2, 3, 4, 5, 6]), filtered down to just the elements from the given array that pass the test (i.e., number % 2 == 0) implemented by the callback function.

Finally, let's discuss the find() method. Here, the problem statement is to find the first number which is greater than 10 in the given array.

// `find()` method 
// PROBLEM STATEMENT: Find the first number which is greater than 10 in the given array

const numbers = [5, 12, 8, 130, 44]
console.log(`Original given array is: [ ${numbers} ]`)

const findGreaterThanTen = numbers.find((number, index, array) => {
  console.log({ number, index, array })
  return number > 10
})

console.log(`Final result is:  ${findGreaterThanTen}`)
console.log(`Original given array after applying find() method is: [ ${numbers} ]`)

//Output:
// Original given array is: [ 5,12,8,130,44 ]
// { number: 5, index: 0, array: [ 5, 12, 8, 130, 44 ] }
// { number: 12, index: 1, array: [ 5, 12, 8, 130, 44 ] }
// Final result is:  12
// Original given array after applying find() method is: [ 5,12,8,130,44 ]

In the above code snippet, the find() method returned the first element (i.e., 12) in the given array (i.e., [5, 12, 8, 130, 44]) that satisfies the test (i.e., number > 10) implemented by the callback function. If none of the values satisfy, it returns undefined.

In conclusion, we compared the arguments of user-supplied "reducer" callback function of reduce() method with callback function of other repeatedly applied array methods like map(), filter(), find() method then we figured out that there was an extra argument present in the reduce() method which was accumulator which is the value resulting from the previous call to callback function.

I Hope that after reading this article, you will not be scared of the reduce() method.