DEV Community

Cover image for The Holy Trinity of Functional Programming: Map, Filter and Reduce
Mikhail Levkovsky
Mikhail Levkovsky

Posted on

The Holy Trinity of Functional Programming: Map, Filter and Reduce

You've watched the Youtube videos, you've done the tutorials on Pluralsight and you consider yourself a Javascript expert.

However, now you want to hang with all of the cool kids and talk about functional programming. For loops are for suckers (well not really), higher order functions are all the rage and you want to understand what this means. Well the very first step is understanding the 3 most popular methods which are: Map, Filter and Reduce.

It's important to understand how and when to use these methods, but more importantly, you also need to know when to avoid them.

To setup some context, let's pretend we have an application that saves basic user information. Let's assume our User entity has the following properties: id, firstName, lastName, date of birth, email, an avatar url, a username and a flag to tell us if they are active or not.

User.ts

If the annotations are not familiar don't worry about it. It's not important for the example and is just some TypeORM specific annotations.

To explore the concepts of map, filter and reduce, we will create a class with the following methods:

1. standardizeAvatars πŸ‘‰ Accepts an array of users, and adds a base url to all of the avatar urls
2. getActiveUsers πŸ‘‰ Accepts an array of users, and returns only the active ones.
3. getAllAges πŸ‘‰ Accepts an array of users, and gets the total age of everyone in the array.

pssst I tweet about code stuff all the time. If you have questions about how to level up your dev skills give me a follow @mlevkov

Map πŸ—Ί

The .map function goes through every single element of an array and applies a passed in function to each element. There is one VERY VERY important point to pay attention to that's not talked about is that the .map function goes through EVERY πŸ‘ SINGLE πŸ‘ ELEMENT πŸ‘ and returns a brand new array with the modified values.

That means you can't break out of the loop AND you will duplicate every single element of the array. If you have a huge collection that takes up a lot of memory, maybe using a good old fashion for loop is better.

Here is an example of how to convert a for loop to .map.

Filter πŸ₯…

The .filter function goes through every single element of an array and checks if that element returns true or false when passed into the passed in function. If it returns true, we keep that element, otherwise we don't. Phew that's a mouthful. Don't worry there's an example below.

Just like .map, the .filter function goes through EVERY πŸ‘ SINGLE πŸ‘ ELEMENT πŸ‘ and returns a new array with just the elements that didn't get filtered out. So while your collection might shrink in size (or might not), you will still go through every single element without the option to break or continue. If you are doing some heavy computation then on every element that you want to keep, then consider using a for loop.

Here is an example of how to convert use .filter and the same example with a for loop.

Reduce πŸ‘¨β€πŸ‘¦

The .reduce function will also go through every single element of an array BUT in this case it will not return you another collection, but a single element. In fact, you can say it "reduces" your collection to one item.

The .reduce function accepts a custom function that you make and a placeholder value that keeps track of the operations. This will guarantee that your collection will shrink in size.

There you have it, how to use the holy trinity of functional programming.

If you want to level up your coding skills, I'm putting together a playbook that includes:

  1. 30+ common code smells & how to fix them

  2. 15+ design pattern practices & how to apply them

  3. 20+ common JS bugs & how to prevent them

Get early access to the Javascript playbook.

Top comments (17)

Collapse
 
hellokyyt profile image
Kyle Harrison • Edited

What I like about this article, is discussing the virtues of why you'd want to use these functions, but juxtaposed with commentary about their weaknesses and why you'd maybe still want to keep the "old" stuff in your toolbelt. Bravo πŸ‘πŸ‘

Collapse
 
mlevkov profile image
Mikhail Levkovsky

much appreciated :)
thanks for taking the time to read it

Collapse
 
jejones3141 profile image
James Jones

There is the monotheistic school that recognizes that map, filter, and reduce are all instances of folding. :) Seriously, good article!

Collapse
 
mlevkov profile image
Mikhail Levkovsky

Much appreciated :)

Collapse
 
chrisachard profile image
Chris Achard

Yes! Really understanding map, filter and reduce really helped as I would read other people's code, and also really helped clean up my own code (especially when writing React and Redux).

Another note about .reduce: you can also reduce into an object or array as well - so look into that if you want to transform one object/collection into another one.

Collapse
 
mlevkov profile image
Mikhail Levkovsky

It's so cool, I use it in my day to day and shorten my functions so much just by introducing these nice high order functions.

Reduce is so powerful! You can compose functions like crazy and just make beautiful poetry with your code. I didn't include it here because it's more of an intro post but would be great to make a more advanced reduce article

Collapse
 
priitpu profile image
Priit • Edited

You put emphasis on the fact that map, filter and reduce go through every single element of the array, that being a theoretical con, compared to a for-loop. Yet your examples don't showcase the use-cases of breaking/continuing so currently the examples are more verbose versions of native methods.

Also for-of loop !== for loop.

Otherwise a good intro to more abstract methods.

Collapse
 
mlevkov profile image
Mikhail Levkovsky

Appreciate the feedback, good point that I didn't dig in how to break out of the for loop. I assumed people knew how to do it but thats maybe a faulty assumption.

Good point about the for-of loop !== for loop, will be more careful in the future :)

Collapse
 
morgboer profile image
Riaan Pietersen • Edited

Great succinct article, Mikhail, thank you for writing it.

Question about your .filter example.
You say that using .filter will loop through everything and create another array that contains the result set.
Then, in the forloop example, you are creating a separate array in any case (const result: User[] = []).

As I see it your forloop approach should avoid creating another array - right? What would the approach be to not create a result set array?
In the past I have avoided creating a duplicate by slicing the unmatched value out of the original array. Would that work?

Collapse
 
anthonybrown profile image
Tony Brown

would you say that these higher order functions are just wrappers for loops?

a friend of mine said that and it threw me off because I thought loops were synchronous and using something like the map function was an asynchronous way of coding?

Great article!

Collapse
 
adipolak profile image
Adi Polak

short, simple and to the point! thank you for supporting a more functional world!

Collapse
 
mlevkov profile image
Mikhail Levkovsky

thank you for taking the time to read :)
much appreciated

Collapse
 
josephthecoder profile image
Joseph Stevens

Spread the FP word! πŸ’―πŸ’―

Collapse
 
ajinspiro profile image
Arun Kumar

Ugh... I think u accidentally copy pasted code for filter in reduce...

Collapse
 
mlevkov profile image
Mikhail Levkovsky

I don't think I did, they just look really similar. Instead of .filter it says .reduce :)

Collapse
 
ajinspiro profile image
Arun Kumar

Apologies, at the time I "really" saw filter instead of reduce. LOL

Collapse
 
jimtomlinson profile image
Jim Tomlinson

Nice succinct article.

Code typo: in the for-loop version of getActiveUsers(), you want to return result, rather than users.