loading...

How The Hell Do I use Map?

lvrbrtsn profile image Levi ᕙ(⇀‸↼‶)ᕗ ・4 min read

This is a post from my personal blog located Here
They are published there a day or so early. How fancy.

I often encourage my students to use the array functions map, reduce, and filter but they rarely feel comfortable with them, which is really a shame because they are like a swiss army knife with a mounted flashlight. These three functions could probably remove thousands of lines of your most confusing buggy code. Let us start with the all-star of the bunch map.

Map is an interesting type of function, it can look extremely strange at first like someone has peeled away the JavaScript you know and love to expose some ancient alien technology.

array.map(x => x * 5) // What r u even Doing tho!!!!

Let's break down this line of code just to achieve a baseline.

First I would like to point out the arrow function x => x * 5 (if you are unfamiliar with what arrow functions are read this Blog Post! where I hopefully explain them pretty well.)

What is a function doing there? Is this a callback? Well... sort of... but no. It kind of helps to think of it as a call back if you want, in that it is a function passed and a*argument, and another function determines its execution... So in a few ways, it is like a callback. Still, it is not a callback, instead, it is referred to as a **Higher Order Function* which is a blog post for another day.

Ok, ok, so map takes a function as an argument... But why? What does it do with it?

Well, map just iterates over your array, meaning it takes each item of the array one by one and passes it into the function you supplied.

So if you were to see this

const scores = [90, 80, 25, 50]

const doubleScores = sores.map(x => x * 2)

Then you could determine that doubleScores will be calculated by taking each item in scores and running it through x => x * 2. So what will that leave us with?

Well, it has to be an array too right, because we need to store 4 results. So we know doubleScores is going to be an array. And it is an array filled with the results of doubling some other arrays contents.

// A way to visualize what map is doing
cosnt scores = [90, 80, 25, 50]
const double = x => x * 2
const doubleScores = [ double(scores[0]),
                       double(scores[1]),
                       double(scores[2]),
                       double(scores[3]) ]

Ok, so then what does map do?

Well, one way to explain it is that it allows you to take a function that expects single items as arguments, like in the above case, a single number. And use this function with an array of many items. Whoa... it's like a pocket for loop that every array is just carrying around with it.

This is actually pretty dope because that means instead of writing for loops, I can write simple functions that are used to operating on single items and just presto-chango use them to transform lists of items. This is really great because for loops have cruft and boilerplate that can mask what the actual intention of the code is. Consider the following code.

const students = [ { name: 'Leroy Jenkins' grade: 55 },
                   { name: 'Tommy Pickles' grade: 98 },
                   { name: 'Mike Tyson' grade: 85 },
                   { name: 'Donnie Darko' grade: 90 } ]

// A simple function expecting a single student, and returns true if they pass the class and fail otherwise.
const isPassing = (student) => student.grade >= 65 ? true : false

// Usage with a single student
const tommyPickles = students[1]
const didTommyPass = isPassing(tommyPickles)

// Usage with the entire list
const classResults = students.map(isPassing)

// Extra credit c-c-combo usage with filter
const onlyWinners = students.filter(isPassing) // more on this next week.

How slick is that? Can you imagine trying to use that function in the middle of a for loop? It would look like a mess, instead, it looks like a beautiful one line declaration. Map gives us superpowers!
And when I say its like a pocket for loop I mean it, literally any for loop can be re-written using map, and it usually turns out much simpler. For example, the above first written as a for loop looks like this

const scores = [90, 80, 25, 50]
const doubleScores = []
for (var i = 0; i < scores.length; i++) {
  doubleScores.push(scores[i] * 2)
}

Eww wtf no. Bring back the map version

const doubleScores = sores.map(x => x * 2)

ohhhh yes... much better.

See the difference? The map version fits on one line, has much less cruft, and makes you look so much cooler... ok maybe that last part is not true. The larger point is true though, there is rarely a need to write for loops if you know your way around map. I actually have not written a for loop in so long that I had to double check MDN when writing the one you see above. I honestly just don't use them much anymore.

Posted on by:

lvrbrtsn profile

Levi ᕙ(⇀‸↼‶)ᕗ

@lvrbrtsn

I help people teach themselves JavaScript @thinkful & @trybloc. Working on my courses. I’m nice at ping pong 🏓

Discussion

markdown guide
 

Array.map is very useful yes.

I think “These three functions could probably remove thousands of lines of your most confusing buggy code.“ is a bit of an overstatement.

Also: there are situations where you’d rather have a for loop than map: if you want to mutate the array in-place (for performance reasons for example).

 

I think it depends. I mostly write React these days and I almost never use a for loop. The nice thing about maps is they implictly return an array, allowing you to avoid all imperative code. They also make it so you are not writing code with side effects.

Performance might be a reason for a for loop, but that eliminates the gains that you get from having immutable data structures in your code.

 

Though I agree that immutability and functional programming are very useful, and I like writing that style of code, you can always come across a situation where a certain amount of performance is necessary so that creating a lot of new data structures or very big ones (like map does) is not an option.

 

If you want to mutate an array in place, you could also use reduce. While it's recommend to create a new array, it is technically possible to mutate an existing array with reduce.

 

it is an overstatement if you are a strong developer writing clear easy to follow loops. Newbies rarely do, good point about perf though!

 

Nice explanation! Simple and concise. 😄

You've got a typo in your second code block:

const doubleScores = sores.map(x => x * 2)

There's a good book that's written for PHP, but provides a good understanding of higher-order functions like map and filter, written by Adam Wathan, called Refactoring to Collections.

It really helped me clean up and understand the work I do, on both front and backend layers.

 

Nice article Levi. But now i'm stuck using old school javascript because of my users still use IE 9. :'(

Just little bit input:

  • When declaring the students, you forgot to put ',' between name and grade.
  • on isPassing method why not make it shorter to (student) => student.grade >= 65 only?
 

Ooh good catch on both! I’ll need to edit this when I can!

 

While we are at typos catching :)

cosnt scores = [90, 80, 25, 50]
 

I find that teaching people that map means basically "Transform", and that reduce is basically "Sum" helps most people. To be fair reduce can be more than summing, but map is really transforming the data so its helpful to think that way I've found.

 

Great article Levi! map is a great tool to add to your toolbox as a developer!

 
 

I understand exactly what you are talking about because I struggle to use map, filter and reduce. Excellent post! Waiting for "How the hell do I use reduce" and "How the hell do I use filter".

 
 
 

Excellent points didn't really consider this! My next title in the series will be more clear. Thanks!