Ruby's map | collect methods explained visually 🎨

Ruby's map | collect methods explained visually 🎨
In: Ruby

There's no way around the map method. Coming from functional programming it's an inevitable part of any developer's everyday life.

Here's an attempt to break it down visually.

Map or Collect?

.map and .collect are aliases, which means they go hand in hand together, doing the exact same thing. No one was ever able to measure the meaningfulness of aliases, but here we are, still alive.

".map() and .collect() do the exact same thing."

How it really works

When you call .map() on a collection, a little gnome with a big finger goes through every element (like in a for-loop) and maps this element to a new element in a new array.

A visual Ruby .map() example

In Ruby, you pass a block to the map method. This block defines what happens to every element from the collection.

In the example above the "collection" is an array, so for every number inside the array, something happens to the number (a transformation operation). Eventually, the transformation is mapped as a new value in a new array at the exact same position as it was in the original array.

In the end, you see that the map method returns a brand new array with the new elements inside.

If you've internalized this example, you've got the gist of it. Just to reiterate a bit on your understanding, though:


This is an absolutely useless operation. You have just robbed the map method of its only purpose: to transform data. You have your original array back, exactly as you passed it. The little gnome was bored, almost to death. You could do something similarly boring if you'd like to finish him:


Here you have an array back with new elements but you haven't used the original elements at all. What a waste.

However useless it may be, at this point you may internalize that everything that the block returns on every iteration, ends up inside the new collection. With map, the one certain thing is that a new array will be returned. And that's already the biggest difference with Ruby's .each() method. The each method also loops through every element of the collection but it doesn't collect all the elements inside a new array in the end (here we go, maybe collect is not that much of a useless name for the alias after all).

Even if you run map on a Set, you will get an array in return:

>> set = Set[1,2]
>> set
=> #<Set: {1, 2}>
>> { |num| num * 2 }
=> [2, 4]
.map() on a Set returns an array
"With .map(), the one thing that's certain is that a new array will be returned."

Even when you do as crazy of a thing as .map! bang. It still returns a collection. But now our little gnome also takes the transformed values and replaces the original collection's values on every iteration.

A mutant array!

So, if you try to assign your map! bang result additionally to a variable, you'll end up with your original collection's values replaced by the new ones and the newly returned collection inside the variable.

By the way, you will get the same type of collection inside your variable as the collection on which you ran .map!. For example, if you run map! on a Ruby Set you'll get a set in return and your original Set gets mutated:

>> original_set = Set[1, 2]
>> original_set
=> #<Set: {1, 2}>
>> variable =! { |num| num * 2 }
>> variable
=> #<Set: {2, 4}>
>> original_set
=> #<Set: {2, 4}>
A Set is returned and you still have your old Set

And last but not least, some Ruby magic 🔮

Numbers become strings 🔮

You pick the method that's available on the object in the collection and put it after &:, a magical key to the world of shortness and conciseness. There's no shorter way to transform values into a new collection. A shorthand that's embraced by Rubyists all over the world. Not only in gnome-land.

More from RichStone Input Output
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to RichStone Input Output.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.