loganward

Logan-Ward

Posted on June 14, 2022

Reducing Reduce

Higher order functions as a whole can be challenging to understand as a novice developer. The thing that separates reduce from its counterparts though, is that reduce is not nearly as immediately intuitive. Filter filters array elements with a function, map changes array elements with a function(admittedly this one only makes sense if you understand the verb form of map), forEach calls a function on each array element, and reduce... reduces the array to a single value? It just doesn't quite make as much sense up front as the others do. So let's _reduce _that confusion.

As silly as it might have sounded, the meaning behind the name of reduce is likely as simple as "reduce the array to a single value." While the common implementations of reduce may not be so straightforward, that can be considered an accurate definition. Another way to think of reduce is as a transformation or condensation. Transform the given array into a data type you need or condense the array into a value you need.

Now let's talk about the syntax of reduce:
array.reduce(function(previous, current, index, array){}, seed)
array in this case is the array we are calling the reduce function on, function is the function we are going to pass each element of the array into, previous is the result of the "reducing" the array that we are building over the course of the reduce call, current is the current element of the calling array, index is the index of the current element, array is the calling array, and seed is the base value of whatever we are trying to reduce the array to. The index and array inputs for the function are optional, include them if you need to have access to those values for your operations. The most important components of this call are the previous and seed values. Previous is what we are manipulating and returning in our passed-in function, and seed is essentially the first value for previous. By default, seed will be set to 0.

Now that we've gone over the syntax, let's see some simple use cases and examples of how to use reduce. The easiest and most directly implicated use for reduce is to get a sum based on the elements of an array like so:

let array = [0, 1, 2, 3];
// prints "6" to the console
console.log(array.reduce((sum, num) => sum + num, 0));
// or
array = [{num: 0}, {num: 1}, {num: 2}, {num: 3}];
// also prints "6" to the console
console.log(array.reduce((sum, ele) => sum + ele.num, 0));
Enter fullscreen mode Exit fullscreen mode

In each call of the passed in function, the current number is added to the sum then returned and assigned to the next sum to continuously update the total. The important thing to remember when using reduce is that whatever you return in the passed-in function will be what is assigned to the "sum" or "previous" value for when the function is called on the next element. Here is an example of getting a count of the elements that pass a certain test:

let array = [0, 1, 2, 3, 4, 5, 6];
// prints "4" to the console
console.log(array.reduce((count, num) => num % 2 === 0 ? ++count : count, 0));
Enter fullscreen mode Exit fullscreen mode

In this implementation of reduce, each call of the passed in function will check whether the current number is even then increment the counter accordingly until a count of the number of array elements that are even has been returned. Using the earlier concept of accessing specific data from more complex elements and this concept of conditionally changing the return value, let's look at some more advanced use-cases for reduce.

Sometimes when calling reduce on an array, we want to use the elements in the array to create a complex data type rather than "reduce" them into a primitive data type like an integer sum or a string. An example:

let array = [
{firstName: 'Bilbo', lastName: 'Swaggins'},
{firstName: 'John', lastName: 'Hancock'},
{firstName: 'She', lastName: 'Ra'}];
// prints an array of the full names of 
// each of the array objects to the console
console.log(array.reduce(function(arr, person){
arr.push(`${person.firstName} ${person.lastName}`);
return arr;
}, []));
Enter fullscreen mode Exit fullscreen mode

For this implementation of reduce, we used the seed value to create an empty array that we then populated with values derived from the elements of the calling array. In the next example we will combine the concepts of filtering elements and constructing a complex data value:

let array = ['a', 'ab', 'abc', 'abcd', 'abcde'];
// prints an object with the two properties being 
// arrays of the string elements that are longer 
// or shorter than 3 respectively to the console
console.log(array.reduce(function(obj, ele){
if(ele.length > 3){
obj.longerThanThree.push(ele);
}
else{
obj.shorterThanThree.push(ele);
}
return obj;
}, {longerThanThree: [], shorterThanThree: []}));
Enter fullscreen mode Exit fullscreen mode

As shown, the reduce function was used here to to both filter the elements and use them to construct a complex data type all in one function call.

Although the examples given here are a bit forced, the less obvious applications of reduce should be more apparent now. Instead of being a nebulous concept of reducing an array, reduce should instead be viewed as a tool to transform the data in an array into a more readily usable form, or condense its elements into a desired result.

💖 💪 🙅 🚩
loganward
Logan-Ward

Posted on June 14, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related