Using .reduce

Friday, September 9, 2022

Reduce might be the most complicated of the three general array methods. It certainly took me a while to figure out just how this method worked.

I will try to break it down and hopefully make it easier for you to understand.

What is .reduce?

Reduce is a method that you call on an array, it will iterate over each element in the array and execute a callback function that you supply. The callback function receives the previous value, the current value, the index and the array that reduce is being called on. Reduce can be given an initial value to start with, otherwise reduce will take the first element of the array as start value and start from the next element.

A small example

Often when things seem difficult, it might help to start out with a small simple example. In the example below, we use .reduce to get the sum of all the numbers in the array.

const exampleArray: number[] = [1, 5, 9, 14];
 
const sumOfAllNumbers = exampleArray.reduce(
  (prevValue, currentValue): number => {
    return prevValue + currentValue;
  },
  0
); // 0 is the initial value.
 
console.log(sumOfAllNumbers); // logs 29.

So what did we do here? We call .reduce on the array of numbers, we give it a callback function that adds the current number to the previous number, and return that value.

Returning is very important here, if you don't return, it won't work.

A more complex example

Let's say, you have an array, with students and the school subject they have chosen. And for some reason, you want an object with inside of it the subject name as the key and the amount of students taking it as the value.

Here is how we would go about doing that using .reduce.

type StudentSubject = {
    name: string
    subject: string
}
// 2 times biology, 2 times math, 1 time history
const exampleArray: StudentSubject[] = [
  { name: "Achraf", subject: "biology" },
  { name: "Sarah", subject: "math" },
  { name: "Alicia", subject: "history" },
  { name: "Mike", subject: "biology" },
  { name: "Nikolas", subject: "math" },
];
 
const groupedByAmount = exampleArray.reduce((prevValue, currentValue) => {
  // Does the subject already exist? If so, add 1.
  if (currentValue.subject in prevValue) {
    prevValue[currentValue.subject]++;
    // Else, initialize by 1
  } else {
    prevValue[currentValue.subject] = 1;
  }
 
  // we need to return the current value
  return prevValue;
}, {});
 
console.log(groupedByAmount); // logs { biology: 2, math: 2, history: 1 }

Should you use reduce?

To be honest, I think reduce is a very handy and awesome function to have. It's flexibility and conciseness is no joke. However I do feel like the readability in a shared or larger codebase is less than optimal. You could argue in most places where you use reduce a simple (for) loop would be both easier to maintain and understand.

At the end of the day, code is not only being written, but also being read. For this reason I would usually try to avoid it if possible. Even if it does make me feel very smart once I write one!