JavaScript Array.reduce() explained with LEGO bricks

We all must agree that JavaScript is great! But you know what? LEGO is even greater! Why? Because you can explain and model so many ideas and behaviors and algorithms using this amazing toy 🚀.

“assorted-color plastic toy lot” by Rick Mason on Unsplash

Definition

The Mozilla Developers Network defines the reduce method in Array object prototype like this:

The reduce() method executes a reducer function (that you provide) on each member of the array resulting in a single output value.
Your reducer function’s returned value is assigned to the accumulator, whose value is remembered across each iteration throughout the array and ultimately becomes the final, single resulting value.

All right, but when and how I can use this function? Is it only for summing all the numbers in an array? Is there a real-world example? And what do this Accumulator (acc), Current Value (cur), Current Index (idx) and Source Array (src) stand for?

🧒🏻 Let’s dive into the kid’s room for a nice explanation.

The colorful blocks

Let’s be honest, I’m a totally incorrigible LEGO addict 🤪. Ah, those colors, shapes, and possibilities to build anything you can imagine out of them…

Now, as I don’t have so much time to spend on them, I prefer to have all the sets built up and displayed on a shelf as they should look like according to the model. But, from time-to-time (especially when the kids get their hands over my precious collection) all of my sets get mixed up and thrown in a big container altogether. Oh, what a mess… And then comes the time for me to gather all my supplies, strength and motivation to bring them back onto their shelves.

But wait, what about reducers? Okay, so before I can restore my displayed collection, I need to build them, and to do that, I need to know which piece belongs to which set. Then I would be able to construct the sets with their instructions (as if I don’t know the instructions by heart 😁).

And here comes the time for my brain to use a perfect array reducer!

Let’s reduce the bricks

Okay, so for the ease of the example, let’s assume that there are no shared blocks among the different sets. So I know, that if I see a black 2x2 block, I know that it belongs to my Star Wars B-Wing Fighter and all my red windows belong to an old family house set. Let’s assume I have only 3 LEGO sets: a B-Wing, a Harry Potter forbidden corridor room and a simple old house with white walls and red roof.

So, here is my container of all the bricks messed up together.

const bricks = [
{set: 'b-wing', type: 'brick', size: '2x2', color: 'black'},
{set: 'house', type: 'roof', size: '4x2', color: 'red'},
{set: 'hp', type: 'spider', size: '1x1', color: 'black'},
{set: 'b-wing', type: 'panel', size: '4x8', color: 'gray'},
{set: 'b-wing', type: 'brick', size: '2x2', color: 'black'},
{set: 'house', type: 'brick', size: '6x1', color: 'white'}
]

I want to arrange them into boxes with LEGO sets like this:

{'b-wing': [], 'house': [], 'hp': []}

📥📥📥 I haven't prepared the labeled boxes, so I will do it along the way, as soon as I stumble upon a piece that doesn’t have a box yet.

So, what I am going to do, is to loop through all the bricks and put each of them into the corresponding box. Here are some statements from the process:

  1. Initially, I have no boxes prepared for each set, but I know that I am going to put the boxes on a special shelf.
  2. I take out a new brick from the initial container, process it in mind, decide where it belongs to, and put the current brick into its set box.
  3. If there is no box for the set of my current piece, I create and label a new box and put it on the shelf.
  4. Each time I take a brick from the initial container, I reduce the number of all bricks left to arrange.
  5. Finally, when there is no brick left in the initial container to process, I look at my shelf and see that my mixed pile of LEGO bricks got transformed into a structured arrangement of labeled boxes on my shelf.

So, in other words (or in visual), I will transform the pile on the left into the organized structure on the right:

The transformation result

👩🏻‍💻 If someone would have coded this whole process in JavaScript using the Array.reduce() method, it would look like this:

const bricks = [....]; //the pile of bricks defined above
const shelf = bricks.reduce((shelfOfBoxes, brick, brickNumber, pile) => {
    console.log(`Checking the brick number ${brickNumber + 1}`);
    if(!shelfOfBoxes.hasOwnProperty(brick.set)) {
shelfOfBoxes[brick.set] = []; //add a new box if needed
}
    shelfOfBoxes[brick.set].push(brick); //put the brick in its box
    console.log(`Bricks left: ${pile.length - (brickNumber + 1)}`)
}, {}); //the empty shelf
console.log(shelf);

And what do we have here?

  1. Initially I have a mixed pile of bricks stored in an array
  2. Initially my shelf is empty. The second argument in the reduce function is the initial value of the shelf, which is an empty object: {}
  3. I loop through the array with the reduce method
  4. In each iteration of the loop I know the following: the current situation on the shelf (shelfOfBoxes), the current brick I’m processing (brick), which is the current index of the brick/how many I have already processed (brickNumber) and the initial bunch of bricks (pile)
  5. During each loop, I check if there is a box with the set name for my current brick on the shelf: if(!shelfOfBoxes.hasOwnProperty(brick.set))
  6. In case there is no box, I add a new empty box with the label of current brick’s set to the shelf: shelfOfBoxes[brick.set] = [];
  7. Then I put the current brick into the box for its set: shelfOfBoxes[brick.set].push(brick);
  8. I note to myself how many bricks are left in the pile: console.log(`Bricks left: ${pile.length — (brickNumber + 1)}`)
  9. In the end I have a shelf of boxes filled with all the bricks that belong to each set box

So I used a reducer function to transform an array of objects into something completely different. That is the purpose of the Array.reduce() method.

Done

Cool, now you should have a clue on what is the reduce method, what are its arguments, and what is a real world example when our brain works like a reducer 🧠.

Of course there are other possibilities and use cases for the Array.reduce() method. You should also know that the initial value of the transformation is optional. I already know another brick-related example for that case. Stay tuned for another article with the detailed explanation coming soon 📢.

And, of course: