Understanding the Reduce Function and How It Can Be Used
Having just completed my first week at Hack Reactor, I now realize that, among many other things, I only had a shallow understanding of the UnderscoreJS reduce function before beginning the program.
What surprised me is that it's actually a very versatile function that can be used to solve a mind-boggling amount of problems. Let's dive a little deeper to see how.
First, what is reduce?
In JavaScript, the reduce function iterates over an array and returns a single value. One of the very simple ways that we can use this function is to add up all of the items in an array. So, for example, if the user gives an array of [1,2,3], the function will return a value of 6.
var array = [1,2,3];
_.reduce(array, function(sum, item) {
return sum + item;
}); // returns 6
When I first learned about reduce, I didn't really understand how the reduce method would make use of an anonymous function like the one used in this example. So, to better understand how the above function works, let's look at an example of how the reduce function can be written:
var reduce = function(array, iterator, accumulator) {
/*
The iterator argument is a function which accepts two arguments.
The arguments for the iterator will be used to compare the current
item in the array with the current value of accumulator.
*/
for (var i = 0; i < array.length; i++) {
/*
The conditional below allows us to set the first item in the
array as the accumulator if the user doesn't pass one in.
*/
if (i === 0 && !accumulator) {
accumulator = array[i];
} else {
/*
Here, the iterator function will do something with the
current accumulated value and the current item in the array.
Accumulator will then be reset to whatever value the
iterator function returns
*/
accumulator = iterator(accumulator, array[i]);
}
}
// After the for loop runs, we return the final value of accumulator
return accumulator;
};
Although there are different ways to write the function, I think this helps to illustrate what is going on under the hood. In the first example where we summed up the array, the array was passed in as the first argument and the anonymous function was passed in as the iterator argument. When the function added up the sum and item in each iteration, we returned that value so that it could become the current sum.
What about if we passed in an accumulator value? Well, the sum would simply start with that accumulator's value before it began iterating over the array.
var array = [1,2,3];
_.reduce(function(sum, item) {
return sum + item;
}, 100); // returns 106
Now for the fun part! Since we have a better idea of how to use the function, let's look at some unconventional ways that we can use the function to solve a problem.
Some (not-so-obvious) examples of how to use reduce
Here is an example of how the function could be used to find the lowest value in an array:
var example = [2,49,15,33,5,1];
var findLowest = function(array) {
return _.reduce(array, function(accumulator, item) {
if (accumulator < item) {
return accumulator;
} else {
return item;
}
});
};
findLowest(example); // returns 1
In this example, let's see if we can use reduce to find out if an array contains a value that we're looking for.
var contains = function(array, target) {
// Returns a boolean value to indicate if the value if contained in
// the array or not
return _.reduce(array, function(wasFound, item) {
if (wasFound) {
return true;
}
// Note: the code in the else if and else statements can be shortened
// to one else statement, but I wanted to write it this way for clarity
else if (item === target) {
return true;
}
else {
return false;
}
}, false);
};
var example = [1,2,3,4,5];
contains(example, 3); // returns true
contains(example, 10); // returns false
In the contains example, we use false as the accumulator (i.e. the start value) so that when reduce iterates over the array, it will keep resetting the accumulator to false if the current item it's checking in the array does not match the target. However, if it does find that the item matches the target value, the accumulator will be set to true, and it will then keep getting reset to true as it continues to iterate.
Hopefully, this will help to provide a better understanding of the awesome power of UnderscoreJS' reduce function.
Rapper turned Soldier turned Software Engineer
