map
basically iterates over the elements of the object:
foo = [
['a', 'b'],
['c', 'd']
]
foo.map{ |ary| puts ary.join(',') }
# >> a,b
# >> c,d
In this example it's passing each sub-array, which is assigned to ary
.
Looking at it a bit differently:
foo.map{ |ary| puts "ary is a #{ary.class}" }
# >> ary is a Array
# >> ary is a Array
Because Ruby lets us assign multiple values at once, that could have been written:
foo.map{ |item1, item2| puts "item1: #{ item1 }, item2: #{ item2 }" }
# >> item1: a, item2: b
# >> item1: c, item2: d
If map
is iterating over an array of hashes, each iteration yields a sub-hash to the block:
foo = [
{'a' => 1},
{'b' => 2}
]
foo.map{ |elem| puts "elem is a #{ elem.class }" }
# >> elem is a Hash
# >> elem is a Hash
If map
is iterating over a hash, each iteration yields the key/value pair to the block:
foo = {
'a' => 1,
'b' => 2
}
foo.map{ |k, v| puts "k: #{k}, v: #{v}" }
# >> k: a, v: 1
# >> k: b, v: 2
However, if you only give the block a single parameter, Ruby will assign both the key and value to the variable so you'll see it as an array:
foo.map{ |ary| puts "ary is a #{ary.class}" }
# >> ary is a Array
# >> ary is a Array
So, you have to be aware of multiple things that are happening as you iterate over the container, and as Ruby passes the values into map
's block.
Beyond all that, it's important to remember that map
is going to return a value, or values, for each thing passed in. map
, AKA collect
, is used to transform the values. It shouldn't be used as a replacement for each
, which only iterates. In all the examples above I didn't really show map
used correctly because I was trying to show what happens to the elements passed in. Typically we'd do something like:
foo = [['a', 'b'], ['c', 'd']]
foo.map{ |ary| ary.join(',') }
# => ["a,b", "c,d"]
Or:
bar = [[1,2], [3,4]]
bar.collect{ |i, j| i * j }
# => [2, 12]
There's also map!
which changes the object being iterated, rather than returns the values. I'd recommend avoiding map!
until you're well aware of why it'd be useful to you, because it seems to confuse people no end unless they understand how variables are passed and how Arrays and Hashes work.
The best thing is to play with map
in IRB. You'll be able to see what's happening more easily.