Andrew Kim Andrew Kim - 4 months ago 9
Ruby Question

Why does map enumerable return value not return expected value

I'm pretty familiar with the Ruby Enumerable module, or at least so I thought. Take the following code snippet:

names = [ "Donald", "Daisy", "Daffy" ]

new_empty_array = []

new_names_array = names.map do |name|
new_empty_array << name
end

puts new_names_array.inspect
# prints [["Donald", "Daisy", "Daffy"], ["Donald", "Daisy", "Daffy"], ["Donald", "Daisy", "Daffy"]]


I know I'm not using
map
correctly, but I was teaching a lesson on Ruby enumerables and came across this example when a student was testing
map
out. The return value of the shovel (
<<
) operator is the array after an element has been added. Shouldn't the result instead be:

[["Donald"], ["Donald", "Daisy"], ["Donald", "Daisy", "Daffy"]]


It seems that the entire loop processes and the final return value of the shovel operator is processed? What gives?

Answer

The result of map, in your case, is an array which consists of references to same array new_empty_array multiple times. You are not creating three different arrays, but modifying the same array in the map block.

To get the output you are expecting, you need to do:

new_names_array = first_names.map do |name|
  (new_empty_array << name).dup
end

As a side note, you could use this code, which is more obvious than the code above, for the output you desire:

(1..first_names.size).map do |num|
  first_names.take(num)
end
#=> [["Donald"], ["Donald", "Daisy"], ["Donald", "Daisy", "Daffy"]]