Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to understand Ruby's .each and .map

Tags:

arrays

ruby

I am having trouble understanding the differences between map and each, and where and when to use them.

I read "What does map do?" and "Ruby Iterators" but wanted some clarification.

If I have:

 z = [1,2,3].map {|x| x + 1}

map takes each element in the array z and adds one to each element, however it does not mutate the original array unless I add !.

On the other hand:

y = [1,2,3].each {|x| x + 1}

returns [1,2,3]. This is confusing to me since:

names = ['danil', 'edmund']
names.each { |name| puts name + ' is a programmer' }

returns:

Danil is a programmer
Edmund is a programmer

What is exactly going on in my second example that isn't allowing each array element to be increased by 1, while in the last example a string is being attached to everything in the array?

All credits go to Speransky Danil, whom I took these examples off of.

like image 768
bill Avatar asked Aug 25 '16 13:08

bill


2 Answers

The map method takes an enum given some block, and iterates through it doing some logic. In your case the logic is x+1. As you say it will not mutate anything unless you use !.

each is simply returning the array that is being called.

Let's take an example of:

names = ["bob"]

If we do:

names.each{|names| names + "somestring"}

the output is still ["bob"]. The reason your second example is different is due to the puts.

As an exercise try doing:

y = [1,2,3].each {|x| puts x + 1}

You will get:

2
3
4
 [1,2,3]
like image 81
Muntasir Alam Avatar answered Oct 05 '22 06:10

Muntasir Alam


tl;dr: I use map if I want to change my collection, apply a transformation on it, end up with something different. I use each if I just need to visit every element in a collection.

Key point is: you should use map if you want to apply a transformation on an array (an enumerable in reality, but let's keep it simple at the beginning). Otherwise, if you don't need to change your array, you can simply use each.

Note that in the code below you are not mutating the array but you are simply take advantage of the local string to print each string with a suffix.

names = ['danil', 'edmund']
names.each { |name| puts name + ' is a programmer' }

Obviously, you could do the same with map but in this case you don't need it and you have to use an each too to print every element. The code would be

names = ['danil', 'edmund']
names.map! { |name| name + ' is a programmer' }
# or names = names.map { |name| name + ' is a programmer' }
name.each { |name| puts name }
like image 39
Ursus Avatar answered Oct 05 '22 06:10

Ursus