# 30 Days Of JavaScript

## Day 11: Higher Order Functions Part 2

### Lesson 4: reduce

Ok, here we go - I've saved the hardest, but most powerful, until last.

`reduce` allows you to change an array to pretty much anything you want, a single number, a long string, a boolean or an object.

Sounds wild right? Well it is, but once you get your head around it, it really is incredibly powerful.

Let's start with the simplest example, reducing an array of numbers to a single value.

First of all the process in plain English:

In plain English we could take a list of numbers `1, 5, 10, 17` and sum them up with `reduce` starting with 0 like this. The key concept here is that the end of each calculation is passed to the next calculation, we start with 0.

• 0 + 1 = 1 ➡️ return 1
• 1 + 5 = 6 ➡️ return 6
• 6 + 10 = 6 ➡️ return 16
• 16 + 17 = 33 ➡️ return 33

And so we get 33 as the result.

Let's look at the code

Ok, don't panic - let's break it down.

This is the function that we give to reduce:

``````1(runningTotal, number) => {
2  return runningTotal + number;
3};``````

That's pretty simple, the function gets given the `runningTotal` and the `number` in the current iteration across the array.

But where does running total come from?

Well if I change the code to this:

``````1(runningTotal, number) => {
2  const newRunningTotal = runningTotal + number;
3  return newRunningTotal;
4};``````

It should become clearer, it's the returned value from the last iteration of this function.

``1console.log(runningTotal);``

Into the playground above on the line above `return runningTotal + number;` then you'll see it get larger each time it runs.

Ok, but where does `runningTotal` first come from you may be asking?

That's what the stray `0` at the end there is doing. It's the initial value that gets passed in on the first iteration. It's optional, but I would say you should always provide an initial value so you don't have any unexpected behavior.

So the full declaration for the function you pass into `.reduce()` is:

``````1array.reduce((previous, current) => {
2  // code that processes previous and current
3  return newValue;
4}, initialValue);``````

`newValue` above is what will be passed in as previous in the next iteration.

Remember, this function will be executed for each item in the array, one after the other and for each iteration the `previous` value and the `current` array element will be passed in.

## Transforming an array

Arguably the most powerful part of `reduce` is how we can use it to transform array into objects.

Let's take a look at a more complicated example to show this off.

``````1const students = [
2  { name: "Harry Potter", house: "Gryffindor" },
3  { name: "Hermione Granger", house: "Gryffindor" },
4  { name: "Ron Weasley", house: "Gryffindor" },
5  { name: "Draco Malfoy", house: "Slytherin" },
6  { name: "Luna Lovegood", house: "Ravenclaw" },
7  { name: "Cho Chang", house: "Ravenclaw" },
8  { name: "Cedric Diggory", house: "Hufflepuff" },
9  { name: "Severus Snape", house: "Slytherin" },
10  { name: "Ginny Weasley", house: "Gryffindor" },
11  { name: "Tom Riddle", house: "Slytherin" },
12  { name: "Sybil Trelawney", house: "Hufflepuff" },
13  { name: "Gilderoy Lockhart", house: "Ravenclaw" },
14];``````

Ok, that's a long list of students and their houses, let's say we want to change the structure of this data and have it look like this:

``````1const school = {
2  Gryffindor: [],
3  Slytherin: [],
4  Ravenclaw: [],
5  Hufflepuff: [],
6  totalStudents: 0,
7};``````

We could do this with a `forEach` like this:

Which is a totally fine and dandy way of transforming the data .... however it's a little messy. We've had to set some data up before and after the main bulk of the work, this requires us to know which houses we have ahead of time (not a problem here but there are plenty of data processing cases like this where that's not the case).

Let's do the same but with reduce instead.

I'll explain the code:

``````1(school, student) => {
2    // explained next
3}, {totalStudents: 0})``````

So this is the function we pass into `reduce()`. Note the initial value, I have set it to `{totalStudents: 0}` with no houses. I could have added the houses here and used the same initial object as in the `forEach()` example but I want to show you a trick for creating an object when you don't know the keys ahead of time. I've set `totalStudents` because I wanted to highlight that you don't have to start with an empty object.

We could have seeded it with `{}` or:

``````1const school = {
2  Gryffindor: [],
3  Slytherin: [],
4  Ravenclaw: [],
5  Hufflepuff: [],
6  totalStudents: 0,
7};``````

Each is fine, it would of course change the code in the body of the function we pass to `reduce()` but that's fine. There's not really a right or wrong here (which is the beauty of `reduce()` as far as I'm concerned ☺️)

Ok, about that trick I wanted to show you when you don't know all the keys your object will have:

``````1if (!school[student.house]) {
2  school[student.house] = [];
3}``````

Because our initial value has no houses (just `totalStudents`) we need to check if the house for this student exists in the `school` object. If it doesn't then add it and create a new array, if it already exists (which it will if we have already added a previous student into this house) then it will skip this step.

``1school[student.house].push(student.name);``

This line is the same as the `forEach` example, we add a student into it's house array.

``1school.totalStudents += 1;``

We know `totalStudents` is on the object as that's the on property we seeded the object with, so we increment it by one.

``1return school;``

We return the `school` object for use in the next iteration.

## Why use `reduce()`?

So you may think:

Ok, that's great but why use `reduce()` here and not stick with the `forEach()` example?

Which is totally fair, the reason being is that you can chain all of these higher order functions together. Here's an example:

Look at that, we've filtered out all the Slytherin students ... if only it had been that simple!

## Challenges

Let's flex your newly found reduction skills. Use reduce to create an object with this structure:

``````1const result = {
2  students: [], // student array like it is now
3  houses: [], // an array of the 4 house names
4  averageAge: 0, // average age of the students
5};``````

This is a is a decent sized challenge and will stretch your brain - that's a good thing. It will really help you learn it 😁

Note that I've added each students rough age

# Go Pro?

Upgrade to Pro for quizzes, tracked progress and a completion certificate for just \$25 🚀

Want more developer tips, tricks and tools?