Sitemap
Up She Rises

musician, coder, drunken sailor

.reduce

--

The next higher-order function I want to tackle here is .reduce

This function can be a bit confusing (I actually only started writing this post after I realized that I had been misunderstanding what the parameters of this function actually were.) This tutorial is an attempt to clarify for myself (and you guys) how this function works. Let’s dive in.

.reduce

I think the name of this function is slightly misleading. EJS mentions that the function is also sometimes referred to as “fold” and I think that’s a better name for it, because it really helps to visualize this function as folding an array back on itself, one index at a time. Sort of like flaking a sail.

As you flake (or fold, or layer, or whatever) each index back onto the previous index, you perform some task on each index, while keeping track of the accumulated result eventually returning a single result — hence “reduce”.

Here’s what the notation looks like in JavaScript:

[code language=”javascript”]
array.reduce(function (a, b){
do something to b here, and keep track of what’s happening with a
}
[/code]
Let’s take a look under the hood at a very basic version of this function:
[code language=”javascript”]
function reduce(array, combiningFunction, accumulatedResult){

forEach(array, function(item){
accumulatedResult = combiningFunction(accumulatedResult, item);
});
return accumulatedResult;
}
[/code]
We are passing accumulatedResult as an argument to combiningFunction. This means we start with whatever the value of accumulatedResult is, and then every time we iterate over a new index, we perform some combiningFunction that combines the value of that new index with our accumulated result. Keep in mind — this is JUST the function that folds up the array. We still have to write the “combiningFunction” part of this — which will tell us what operation to perform on the two indexes. Let’s do that now:
[code language=”javascript”]
function sum(a,b){
return a + b;
}
[/code]
This is just one example of what we might want to do with those indexes. Here, I am adding them together, to get the sum of all the numbers in the array. Note that the combining function has to take TWO parameters, because we are operating on two indexes at a time (unlike .map or .filter, where we are dealing with one element at a time.) Here’s another common thing we might want to do with an array:
[code language=”javascript”]
function findBigger(a,b){
if (a > b){
return a;
}
else {return b;}
}
[/code]
Here, we are comparing the two folded indexes, and returning the bigger of the two. Our reduce function will run this along the entire array, eventually returning the biggest element.

One nifty thing about the built-in JavaScript version of this function is that you don’t have to indicate a starting value. If you don’t JavaScript will automatically use array[0] as the accumulatedResult (i.e. beginning), and array[1] as the first index to be tallied.

Let’s put all of this together:

[code language=”javascript”]
//in this example, I am leaving out the starting value
//-in JavaScript, reduce is optimized to handle this
//it will take use array[0] as the starting point and array[1]
//as the first item to be reduced.
//The version I wrote above is NOT optimized to do this
function reduce(array, combiningFunction)
var currentResult = 0; //this is our initial value
var i = 0; //this is the counter for our for loop
for(i ; i < array.length ; i++){
currentResult = combiningFunction(currentResult, array[i]);
}
return currentResult;

//define our combiningFunction — let’s sum this array
function sum(a,b){
return a + b;
}
//now, let’s call our reduce function, passing the combiningFunction and an array as arguments:
reduce([1,2,3,4,5], sum);
//15
[/code]
Our reduce function ran our sum function on every two indexes, adding them together, returning our final result 1 + 2 + 3 + 4 + 5 = 15. Neat!

But wait…there’s more!

Get Lizzie Shipton’s stories in your inbox

Join Medium for free to get updates from this writer.

Adding up all the numbers in an array is cool, but reduce can do WAY more than that. You can pass pretty much anything as an accumulatedResult — an array, an object, a Boolean, etc. and reduce will reduce the array down to that one thing. What does that mean? Let’s take a look:

[code language=”javascript”]
//let’s say we want to check all the values of an array
//to see if they are all truthy.
//We can use reduce to do this.
var array = [true, 1, {}] //these are all truthy values
array.reduce( function(status, item) {
return status && Boolean(item);
}, true);
[/code]

Whaaaaat? WTF is that?

Let’s break it down.

First, let’s look at the arguments of our reduce function:
our first argument is an anonymous function — this is our combinerFunction. (We don’t need to pass array as an argument within the parentheses because we are calling reduce on array with a dot.)
our second argument is waaaaay down there at the bottom, outside the last curly brace — see it? It’s that little word ‘true.’ This is our accumulatedResult. It will be passed to the combinerFunction as the starting value (status), and it will be returned when reduce finishes iterating.

The trick is, along the way, that accumulated value will be altered by the anonymous function. In this case, we are calling a function that only returns when both conditions on either side of the ‘&&’ operator are true (if either expression is false, && will return false.) The first condition is our status, which will start as true and then be updated on each iteration based on the result of the previous iteration.

So, when all is said and done, reduce will return either false or true, depending

Implementing the built-in JavaScript version of this is, obviously, much easier. Because you will usually store the array in a variable and call the reduce function using dot notation, you only have to define the combining function (making sure to pass it two parameters):

[code language=”javascript”]
var array = [1,2,3,4,5];
array.reduce(function (a,b){
return a + b;
}
//15
[/code]

or:

[code language=”javascript”]
var array = [1,2,3,4,5];
array.reduce(function (a,b){
if (a > b){
return a;
}
else { return b; }
}
// 5
[/code]

Man! My brain has been reduced to a puddle of Jell-o after all that! *drumfill*

Time to take a break, and then go practice what I’ve learned at http://reactivex.io/learnrx/ — seriously, if you haven’t been to this site yet, get on it!

That’s all for today. Thanks, and happy whatever-you-do!

--

--