The Complete Guide To JavaScript's .reduce() Function (With Real-world Examples)
Tags: codenewbie, webdev, javascript, beginners
Published: 2022-12-31 03:55:20

In this guide we are going to cover:
* What is the .reduce() function?
* Creating our version of the .reduce() function
* Calculating the total items and price for a e-commerce shopping cart 
* Creating an array of unique categories for a restaurant menu
* Removing duplicate objects from the array
* Replacing .filter().map() with .reduce()
* Grouping objects by key (Similar to SQL GROUP BY or C#'s .GroupBy())
* How to flatten an array of arrays

[Link for all code snippets used in this guide](https://github.com/gustavupp/Short-Projects/blob/main/AlgorithmsAndDataStructures/reduceExamples.js)

##It seems confusing at first

If you have ever struggled to understand the .reduce() function, you are not alone. It takes messing about with it a couple of times to really understand how it works and use it with confidence.

Most of the examples out there use a simple array of numbers or strings, but the reality is that we normally work with complex objects which is rarely covered.

But before we jump in.
Here's how you can get more out of this content.

* Open your code edtitor and try the examples yourself
* tinker with it (alter values, add or remove elements to/from the array, etc)
* If you find yourself lost in one of the examples, track down the value of the variables either with a pen and paper or on your code editor.

Let's get started!
 

## What is the .reduce() function?

It is a method that executes a callback function on each element of an array. 
* The return value from the calculation is passed on to the next element. 
* In the first iteration, there is no "return value of the previous calculation", if passed in, a initial value can be used in it's place. 
* Otherwise, the first element of the array is used as the initial value and iteration starts from the next element.

To put it simply, it is just a variable and a loop.
* The variable holds the new value
* The loop iterates over the array so we can grab what we want from each element

This:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rlb58wi7p4fx47u6jual.png)

Achieves the same as this:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cs3my28wqisj23jj8br9.png)

Pretty much every time you need to use a variable and a loop, you can replace it with the reduce function.

As there is no better way of learning than actually trying things out, let's build our version of the .reduce() method so we can really understand it.



## Building our own .reduce()

Let's do it by solving a simple problem: 
We have an array of numbers and we want the sum of all of them.

It is just like the example above of a variable and a loop.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rlb58wi7p4fx47u6jual.png)

**We need 3 things:**
- an array 
- a variable that holds the total value `total`(usually called the accumulator)
- a loop to iterate over the array

Let's say you want to turn it into a function so you can use it easily, how would you do it?

Maybe something along these lines:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nf7qolc5n0lbi19lc4ol.png)

* We pass the array as a parameter into our function
* We return `total` at the end.

That is looking good, but what if we want the option to set the initial value of the variable `total`? 
We can add the option as another parameter and set `total` to its value.

Like so:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rbwke6oscwrp7n80q4qx.png)

But there are still 2 problems with this function. 

1. There is no way we can add different logic to be executed inside the loop (It only adds the current element to the `sum` variable)
2. It works only on simple arrays (where each item is a value type, not an object)

I'll show you what I mean.

Let's create an array of objects this time

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wj081fcwz3y35pdks86v.png)

Let's invoke our myReducer function passing in the array of objects

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zlaydwql31yrsgsjpmii.png)

It doesn't work because the value we want to add is inside the object and not the object itself. 
We have to access it as `total += arr[i].number`

But this function didn't account for that. 

However, if we add a callback function as a second parameter, we can:
- Execute the callback function on each element of the array
- Create any custom logic we need

Let's modify our `myReducer` function.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8o50kemtzdf3t5cpo6zp.png)

Let's test it again with the objects array.

First, declare the callback function and call `myReduce` passing it in.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ijuvd12pth51gdcxkm04.png)

Note that we added `if` and `else` conditions based on the value of `total` which is our initialValue option.

1. If `initialValue` is not given
 * it doesn't execute the callback on 1st iteration
 * There is nothing to add, initialValue is undefined.
 * just set `total` to the value of the current element

2. If `initialValue` is given
 * It executes the callback on all iterations

That is pretty much what the original `Array.prototype.reduce()` does.

The main difference is that there's no need to pass the array as an argument as the original `.reduce()` is bound to `Array.prototype` so the array is always the array upon which `.reduce()` was called. 



## Calculate total items and price for an ecommerce shopping cart

Say you have an array like this one:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ht9f3f1d9cqkwoek907.png)

And you need to reduce this array into an object like this `{ totalItems: 0, totalPrice: 0 }` so we can display the correct information on the checkout page.

This is how we can do it:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/42hsycrt1xmwys6vd0k5.png)



## Create an array of unique categories for a restaurant menu

Given this array:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ya18qnzn8f03pqivp1zh.png)

We need to reduce it into an array of unique categories like `['Appetizer','Entree','Main']`

This is how we can do it:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7d253qu7r0191usgy2cx.png)


## Removing duplicate objects from the array

Similar to the example above, but this time we need to return the same array of objects filtered with only unique objects.

This is the array with a duplicate object:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l0c5syyo5j02ymv9czce.png)

Note: You have to have a property similar to `id` that is unique for each object

This is how we can create another array with only unique elements:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8rmzbe0cintt6vnjjn5f.png)



##Replace .filter().map() with .reduce()

It's very common having to filter an array and then modify the elements of the filtered array.

We will use the same array of the menu categories above

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/80emyfw0mgn8wxrjp0mp.png)

But this time we want to get an array with the `itemName` only of the items whose category is 'Entree'

We can use .filter() the array and then .map() to accomplish it

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4l32avcddc8q93mca9v4.png)

Or we can do it with .reduce()

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ras2x6nf6twptyk837x.png)

The advantage of using .reduce() is that you iterate over the array only once.


##Group objects by key (Similar to SQL GROUP BY or C#'s .GroupBy())

This is the one I like the most. This is a very handy function that will be included in JavaScript's array methods in probably on next update (currently on stage 3 for approval)

This groupBy function can also be used as a middle step to solving more complex problems.

We again will use the menu categories array:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a0e2d9ij3y0g2kc60zsf.png)

This is our groupBy function:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/411foq0g29k850hb7kja.png)

It can get even handier if we add the option to pass the `key` as a function.

Just replace this line:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uvt6dwpsae5r1jepmhk1.png)

With this one:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ursvb7gg8clww8wtpii5.png)

This way we can call it and pass a function that returns the key, as opposed to writing the string ourselves, avoiding typos.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jcwknn60or4w3ogkrcye.png)


##How to flatten an array of arrays

This is a one-liner to flatten an array of arrays:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4bvb0o7hs4h14wgu7msk.png)

Note: It only works with one level of nesting. For multiple levels you have to write a recursive version.

## Conclusion

In this article we have learned:
* What is the .reduce() function
* How to create our version of the .reduce() function
* To calculate the total items and price for an e-commerce shopping cart 
* To create an array of unique categories for a restaurant menu
* To remove duplicate objects from the array
* To replace .filter().map() with .reduce()
* How to group objects by key (Similar to SQL GROUP BY or C#'s .GroupBy())
* How to flatten an array of arrays

Thanks for reading! 

If you like this article:
* Leave a comment below
* Follow me on Twitter [@theguspear](https://twitter.com/theguspear) for more content like this one.

Catch you later, 

Gus.