2016-07-19 7 views
3

Я довольно знаком с модулем Ruby Enumerable или, по крайней мере, так думал. Рассмотрим следующий фрагмент кода:Почему map перечислимое возвращаемое значение не возвращает ожидаемое значение

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"]] 

Я знаю, что я не использую map правильно, но я учил урок на Руби перечислимых и наткнулся на этот пример, когда студент испытывал map аут. Возвращаемое значение оператора лопаты (<<) - это массив после добавления элемента. Не следует ли результат вместо того, чтобы быть:

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

Кажется, что все процессы цикла и конечное значение обратного оператора лопаты обрабатываются? Что дает?

+1

должен быть '' names' first_names'? – squiguy

ответ

5

Результат map, в вашем случае, представляет собой массив, который состоит из ссылок на один и тот же массив new_empty_array несколько раз. Вы не создаете три разных массива, но изменяете один и тот же массив в блоке map.

Чтобы получить вывод, который вы ожидаете, что вам нужно сделать:

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

В качестве примечания, вы можете использовать этот код, который является более очевидным, чем код выше, для вывода вы желаете:

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

Позвольте мне получить это прямо, возвращаемое значение для каждой итерации - 'new_empty_array', и поскольку последняя итерация' .map' возвращает массив с 3 элементами, то, что возвращается с карты, является 'new_empty_array' в последнем состоянии 3 times –

+0

@AndrewKim 'new_empty_array' является ссылкой на массив, и вы возвращаете ссылку на него на карте и, следовательно, заканчиваете с 3 ссылками на него как на массив - все 3 ссылки указывают на тот же физический массив, который в конце итерации имеет 3 элементы –

0
new_names_array = first_names.map do |name| 
    name 
end 

даст ["Donald", "Daisy", "Daffy"].

Каждый элемент first_names возвращает значение в новый массив, созданный map, но вместо этого вы возвращаете для каждого элемента новый массив, new_empty_array.

Этот объект << три раза и в конце имеет три названия, так 3 х 3 элемента:

[new_empty_array, new_empty_array, new_empty_array] = [["Donald", "Daisy", "Daffy"], ["Donald", "Daisy", "Daffy"], ["Donald", "Daisy", "Daffy"]] 
+0

@ the Tin Man, thnx снова для редактирования. Вы должны вкладывать много времени в исправление неанглийских людей, таких как я. – peter

+0

Возможно, вы имели в виду 'неанглийское письмо людей' ;-) –