3

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?

1
  • 1
    Is first_names supposed to be names? Commented Jul 19, 2016 at 20:26

2 Answers 2

5

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"]]
Sign up to request clarification or add additional context in comments.

2 Comments

Let me get this straight, the return value for each iteration is new_empty_array and because the last iteration of the .map returns an array with 3 elements, what gets returned from the map is new_empty_array in it's last state 3 times
@AndrewKim new_empty_array is reference to an array, and you return reference to it in map and hence, end up with 3 references to it as array - all 3 references point to same physical array which at the end of iteration has 3 elements
0
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"]]

2 Comments

@the Tin Man, thnx again for the edit, You must be investing a lot of time in correcting non english speaking people like me
May be you meant non english writing people ;-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.