Pull to refresh

Cracking Reduce Concept In Just 10 Minutes

Reading time 3 min
Views 1.4K


Being a developer, I love to code especially in JavaScript. As per my experience, using reduce function is one of the toughest tasks in JS. Let me first elaborate on the Reduce concept!

In Wikipedia, it has many names viz.

Reduce
Fold
Accumulate
Aggregate
Compress

It is a function that folds a list into any data type. It's all about breaking a structure down into a single value. It's like folding a box! With reduce, you can turn an array [1,2,3,4,5] into the number 15 by adding them all up.

How it was done in the past?

Suppose you might need a loop to fold a list into a number, you can do like this:

const add = (x, y) => x + y;
const numbers = [1, 2, 3, 4, 5];
let total = 0;

for (let i = 0; i < numbers.length; i++) {
    total = add(total, numbers[i]);
}

console.log(total);

However, using reduce function, you just need a loop to handle along with “add function”. The code will be like:

const add = (x, y) => x + y;
const numbers = [1, 2, 3, 4, 5];

numbers.reduce(add);

See, this is how it has made easy coding!

For now, pay attention to JavaScript which cannot use loops, recursion or array methods such as forEach, some, find, etc. So, only three left are map, filter and reduce. However, our work as programmers has not changed. We still need three types of functionality in our apps.

-> Filtering lists
-> Transforming lists
-> Converting lists into data types viz. string, boolean, number, object

The above challenge can be easily handled with tools filter, map and reduce.

Array.filter judges lists

What happens if you want a new list with some items removed, such as when the user searches your contact list? Hence, simply create a function that returns true or false based on its input (a predicate).

const isEven = (x) => x % 2 === 0;


Now, plug it into a filter to apply that against an entire list.

const numbers = [1, 2, 3, 4, 5];
numbers.filter(isEven);

Array.map transforms lists

Converting lists to other lists is Front-End development in a nutshell. Therefore, the map covers much of your list work.

Let's say our application calls an API for the list of users, and we need to show each user's name on the screen. Simply create a function that returns a user's name.

const getUserName = (user) => user.name;

Now, plug it into the map to run that against an entire list of the users.

users.map(getUserName)

Array.reduce can do it for you

Array.reduce uses two parameters

1) An initial value(which is optional)

If you don’t supply initial value then reduce function defaults to the list's first element.

For summing plain numbers, you will write:

[1, 2, 3].reduce((total, current) => total + current);/source>
In case, you give an initial value of zero, you will use this code:

<source lang="markdown">
[{ age: 1 }, { age: 2 }, { age: 3 }]
    .reduce((total, obj) => total + obj.age, 0);

2) The reducer

When reduce loops over the list, it feeds below two parameters to the reducer:

-> Current value: The current value is self-explanatory, just like when you use the matrix [i] in a regular loop. However, the accumulator is a computer term that sounds scary and is actually simple.

-> Accumulator: When you're browsing users, how do you track their total age? You need some counter variable to keep it. That is the accumulator. It is the final value that will be reduced when finished.

At each step of the cycle, it feeds the last accumulator and the current element to its reducer. What the reducer returns becomes the next accumulator. The cycle ends when the list ends and has a single reduced value.

If you feel map and filter functions are not enough, you can run the game with reduce. It can do all that map and filter is doing and all other things involving loop over an array.

Let's take the help of an example to calculate the age of the users. Consider users' ages to be 29,30, 31 and 32.

const users = [
  { name: 'Mariam', age: 29 },
  { name: 'Kenstar', age: 30 },
  { name: 'Saransh', age: 31 },
  { name: 'Geoffie', age: 32 },
];

On the other hand, map and filter can only return arrays, but we need a number!

users.map(?);
users.filter(?);

If we had loops we'd just go through users and tally their ages in a counter! However, it can be easier to reduce function.

users.reduce((total, currentUser) => total + currentUser.age, 0);

Now, using console.log at each step can be the easiest way to handle above.

const users = [
  { name: 'Mariam', age: 29 },
  { name: 'Kenstar', age: 30 },
  { name: 'Saransh', age: 31 },
  { name: 'Geoffie', age: 32 },
];

const reducer = (total, currentUser) => {
    console.log('current total:', total);
    console.log('currentUser:', currentUser);
    
    // just for spacing
    console.log('\n');
    
    return total + currentUser.age;
}

users.reduce(reducer, 0);

Summarizing the whole code in 6 steps here:

-> First, define reduce function and its 3 parameters.
-> By providing the initial-value, initialize the accumulator. It will change every loop.
-> Now, start looping over the given array.
-> Capture the currentItem of the array for that cycle.
-> It's time to call reducer with accumulator & currentItem and saving it as a new accumulator
-> Lastly, the accumulator is done changing when the loop is finished and return it.
Tags:
Hubs:
+4
Comments 0
Comments Leave a comment

Articles