Reputation: 3335
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?
Upvotes: 3
Views: 144
Reputation: 42182
new_names_array = first_names.map do |name|
name
end
would give ["Donald", "Daisy", "Daffy"]
.
Each element of first_names
returns a value to the new array created by map
but instead you return for each element a new array, new_empty_array
.
This object is <<
three times and at the end has the three names, so 3 x 3 elements:
[new_empty_array, new_empty_array, new_empty_array] = [["Donald", "Daisy", "Daffy"], ["Donald", "Daisy", "Daffy"], ["Donald", "Daisy", "Daffy"]]
Upvotes: 0
Reputation: 18762
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"]]
Upvotes: 5