Ruby Tuesday – Enumerable#map aka collect

Today’s Ruby Tuesday method is Enumerable#map, also known as Enumerable#collect.

Enumerable#map is a function with a long lineage. Enumerable#map takes a set of items, and maps the inputs onto a new set of values via a transformation function, or in the case of Ruby, a block.

[1, 2, 3, 4].map{ |x| x + 1 }
# => [2, 3, 4, 5]
[1, 2, 3, 4].map{ |x| x * x }
# => [1, 4, 9, 16]

In Ruby, the map method is an alias of Enumerable#collect.

[1, 2, 3, 4].map{ |x| x * x }
# => [1, 4, 9, 16]
[1, 2, 3, 4].collect{ |x| x * x }
# => [1, 4, 9, 16]

Ruby also has some ways of taking existing methods, and passing them as the block to be invoked by the map function. If we want to do a transform by calling a method on the object passed to the block, we can prepend the name of the method with a &: and pass that to the map function as an argument.

['i', 'b', 'm'].map{ |x| x.upcase }
=> ["I", "B", "M"]
['i', 'b', 'm'].map(&:upcase)
=> ["I", "B", "M"]

You want to be careful with this though, as not all functions on an object are transformation functions but may modify the underlying object, which may cause confusion to readers of your code if they are expecting the original enumeration to be unchanged.

items = ['i', 'b', 'm']
# => ["i", "b", "m"]
items.map(&:upcase)
# => ["I", "B", "M"]
items
# => ["i", "b", "m"]
items = ['i', 'b', 'm']
# => ["i", "b", "m"]
items.map(&:upcase!)
#=> ["I", "B", "M"]
items
# => ["I", "B", "M"]