In your example, when you want to print each value individually right away, each
is better. map
is useful when you want to save the new versions your elements back into an array, and use that data later in your program.
For instance, say you wanted to forget whether the names had ever been lower or uppercase. Everywhere in your program, the names will be uppercase, so you just want to convert them to uppercase now and be done with that.
a = ["kevin","john","ryan"]
a = a.map{ |n| n.upcase }
Compare that to using each
– you would have to use each_with_index
, actually, since you need a way to assign the new values back:
a = ["kevin","john","ryan"]
a.each_with_index do |n, i|
a[i] = n.upcase
end
This is the kind of situation map
is for. Getting a new Enumerable
with changed values, so that you can use the new values later.
By the way, as a shortcut, if you’re assigning a map
ped variable back to itself, instead of a = a.map{}
, you can use a.map!{}
.
Another situation is if you wanted to print all names with an even number of letters. If you used each
, here’s how it would look:
a = ["kevin","john","ryan"]
a.each do |n|
if n.size.even?
puts n.upcase
end
end
If you used map
, that would give you an array back. Then you could pass that array to select
, and finally use each
to print the values. This separates the steps more clearly for anyone reading the code, and makes your code more modular if you want to extend it later.
a = ["kevin","john","ryan"]
a.map(&:upcase) \
.select{ |n| n.size.even? } \
.each{ |n| puts n }
The last line could also be this:
.each(&Kernel.method(:puts))
but that is probably unnecessarily confusing for such a small bit of code. What that does is convert the global puts
method into a block using the &
operator. Kernel
holds all global methods, and .method
is the way you get a variable with a method from a class. So .each(&Kernel.method(:puts))
says “get the global puts
method, and turn it into a block so that puts
is called with the block arguments as parameters”. But in this case, it’s clearer and simpler to write .each{ |n| puts n }
.