Reduce? Do I make stuff smaller? Less… er?

Well… Yes and no.

The idea behind reduce is a simple, but a very powerful, one. It allows you to take an array of data and transform it into almost anything that you can imagine.

MDN defines reduce as:

The reduce() method executes a reducer function (that you provide) on each member of the array resulting in a single output value.

That’s a nice definition which may lead you to believe that you always have to produce one value, like a number or a string. While technically true, you can still produce another array (which holds many values) or an object (as complex as you want it) or an array of objects. That means that you can reduce an array of 3 strings to one number or to an array of 200 very complex objects. Now, if that isn’t powerful, I don’t know what is.

How does it work?

reduce is like one of those games where you can grasp the rules in an hour or two but still discover new ways of having fun for years to come.

In itself, the inner workings of reduce are simple.

An abstract recipe would be:

take an array of values, add a function which will run on every element, make sure that the function returns a value, use that returned value when running on the next element, add a pinch of salt, accept the return of the function at the last element as your final value.

In short — you are building up to the final value by always having the result of the function running on the previous element.

Here is an example of building up an object from an array of values:

As you can see, we start building up the object immediately and keep changing values as we are working through the array. Don’t worry if you don’t know how it happens yet, the important message is that you are always carrying your result and modifying it as you are working through your values.

Starting small

I hope that I could sell you on the idea of how powerful reduce is. The logical next step would be to start small and build up your knowledge of reduce . I hope that by the end of this article, you’ll be able to solve a wide range of problems in an elegant fashion.

Higher-order functions

There is one more concept that we need to get out of the way before digging into reducing all the things and that’s the concept of higher-order functions.

Wikipedia defines them as:

In mathematics and computer science, a higher-order function is a function that does at least one of the following:

- takes one or more functions as arguments (i.e. procedural parameters),

- returns a function as its result.

The first point is the one we’re interested in. reduce is a higher-order function because it takes a function as an argument — exactly the function we’ve already mentioned, the one which is going to get applied to each element.

Start reducing

The basic reduce function is easy to define:

myArray.reduce(callbackFunction, initialValue)

Basically, this is going to take an array and run the given callback function over all the elements in the array. Each function call (each step) will deliver a returning value. This returning value is going to get passed into the next step.

You may rightfully ask: what about the first element of the array? Where is the “result” from the previous step? That’s a very good question! That’s why reduce accepts another parameter — initialValue . We can hard code what the initial value is going to be for the first element, as if it was a return from a previous element. For example: if we were to write a function which would sum up all the numbers in an array (spoiler: which we are going to do), a natural initial value would be a zero because it’s a great starting point for addition.

Highly functional

With the basic reduce defined, let’s talk about callbackFunction . The callback function, which is going to get called for each element and will receive the result from the previous call looks like this:

const callbackFunction = function(

accumulator,

currentValue,

currentIndex,

array) { ... }

Although this seems a little intimidating at first, it’s actually quite easy to grasp:

accumulator represents the returned value from the previous function call. If we’re at the first element, you’ve probably guessed it, it’s going to contain initialValue .

represents the returned value from the previous function call. If we’re at the first element, you’ve probably guessed it, it’s going to contain . currentValue is the current element of the array upon which the function is being called.

is the current element of the array upon which the function is being called. currentIndex represents the index of the current element.

represents the index of the current element. array is the array which we are reducing right now.

Most of the time, you’ll be interested in the accumulator and currentValue because they’ll allow you to build up your final result. accumulator and array are nice to haves to work with even more complex reducing logic (where you need to know how much of the array you’ve already traversed).

If you ever need a refresher on what each part of a reducer does, here’s a handy image: