How to never use loops again with map, filter and reduce?

Here is a piece of code,┬áit’s purpose is to manage employees’ salary bonuses due to holidays.

Was it ugly? Was it difficult to follow? Were there too many variables? And isn’t it too much verbose? The main problem with this code is that it is not straight to the point.

Lets refactor it so it could lose some sense of repetitiveness.

Replacing loops with map filter & reduce

Here is an alternative nice code:

I successfully eliminated any usage of loops. Notice how short it is. Notice that we got rid of variables such as extra, newEmps and others. The code is less verbose, it is straight to the point.

Now let’s dive deep on how each of the function refactored, so we could have some better understanding on map, filter & reduce.

Filter

Filter loops over a list and checks each item with a predicate function. If the function returns true, the item remains, otherwise it is filtered. An example:

Boys are persons who are children and males.

If you are not familiar with arrow functions whey are kinda nice, a synonym statement would have looked like this:

Map

Map loops over a list and apply a function on each item. All of the results are collected into a new list that returns. An example:

Men are grown boys.

Notice that hopefully grow is a pure function and thus, boys and men are two different lists.

Reduce

Reduce loops over a list and returns a single value out of it. Depending on an iteratee function sent, reduce sums, multiplies or does any other operation. Example:

In the example above, if population consists of 4 people, then iteratee function would have been called 4 times. In other words, if we called the ireratee function countSavings, for the sake of example, then the above reduce function produces the same value as this code:

Bonus Section – How to avoid looping over functions?

If some of the things are still unclear at this point, it is a good idea to read again the salary example refactored and examine it a little further.

Lets go back to our salary example above. Say that salary calculation task was way more complex, in fact it is. If in order to calculate it, we would need a vast amount of functions, how would we do it?

Assuming emp has an array of salary transactions, something like:

Then surely we had to loop over this functions and

Don’t be so sure. There is also a way to eliminate this loop away. Read carefully and twice:

Lets examine the expression above, beginning with (arg, func) => func(arg):
This function accepts two parameters, first is an argument, second is a function. The return value is that which the function (2nd parameter) will return when given the arugment (1st parameter). So for instance, if we call this weird entity kindDavid just for the sake of example, then:
kingDavid(3,x=>x+4) is 7
and
kingDavid(13.5,x=> x==13.5) is true
and more importantly
kingDavid(emp, calculateSalary) is calculateSalary(emp)

Because calculateSalary is a function returning a new emp object it can work perfectly with reduce. First iteration will apply: (emp, emp.transactions[0]) which will return emp.transactions[0](emp). This is actually a new emp with calculated salary. It is now to be sent as a first argument in (result, emp.transactions[1]), which will return emp.transactions[1](result), and so on… Until all the transaction functions applied on a single emp.

The below code emphasizes it:

Want to know more?

Hit

npm install lodash --save

Then

const _ = require('lodash');

And play with it. Full documentation is here.

Summary

If you don’t like your code too straight to the point, use loops.

Subscribe

Leave a Reply

Your email address will not be published. Required fields are marked *