2010-12-12 2 views
0

Извините за смутный вопрос. Я не понимаю слов, чтобы описать это явление, поэтому Google не очень помог. Пожалуйста, обратите внимание на следующий код:Что случилось с тем, как рубин меняет переменные таким образом?

array = [["name", "age"]] 
a = [] 

x = ["Joe 32", 
    "Tom 45", 
    "Jim 36"] 

x.each do |line| 
    name, age = line.split(/\s/) 
    a[0] = name 
    a[1] = age 

    array.push(a) 
end 

array.each do |x| 
    puts x.join(" ") 
end 

Это производит:

name age 
Jim 36 
Jim 36 
Jim 36 

что противоречит тому, что я ожидал:

name age 
Joe 32 
Tom 45 
Jim 36 

Почему array пострадавших после факта путем изменения a?

ответ

5

Вы хотите установить a в новый объект Array внутри each. На данный момент вы нажимаете на массив a, поэтому он возвращает одно и то же значение три раза. Еще лучше было бы не использовать a вообще и вместо того, чтобы преобразовать код в нечто вроде этого:

x.each do |line| 
    name, age = line.split(/\s/) 
    array.push([name, age]) 
end 

Вы могли бы сделать его меньше, чем даже при перемещении line.split быть в методе push, но я думаю, что уменьшает читаемость и не объясняет, какую информацию вы получаете из split.

+1

Да, вы должны понимать, указатели, даже если они не называются указателями. –

+0

Это работает, хотя я до сих пор не понимаю, почему оригинал этого не сделал. Думаю, я посмотрю на указатели. Спасибо – jack

0

Это немного более продвинутый, но построить на ответ Райана, а не делать

x.each do |line| 
    name, age = line.split(/\s/) 
    array.push([name, age]) 
end 

, вы можете использовать функцию map, и имеют

people = x.map do |line| 
    name, age = line.split(/\s/) 
    [name, age] 
end 

desired_result = [["name", "age"]] + people 

Это немного больше " функционального программирования ". Я уверен, что это очень грубое резюме, но в функциональном программировании вы не изменяете существующие объекты, вместо этого вы создаете новые объекты.

Как и в сторону, если вы хотите, чтобы проверить ответ Райана, вы могли бы использовать object_id на каждом из объектов:

array.each_with_index do |object, index| 
    puts "Object #{index} (which is #{object.inspect}) has an object id of #{object.object_id}" 
end 

который дает

Object 0 (which is ["name", "age"]) has an object id of 10204144 
Object 1 (which is ["Jim", "36"]) has an object id of 10248384 
Object 2 (which is ["Jim", "36"]) has an object id of 10248384 
Object 3 (which is ["Jim", "36"]) has an object id of 10248384 
+0

Спасибо, Андрей. Я имею в виду изучить функциональное программирование с помощью Ruby. Это отличный пример того, как это сделать. – jack

+0

@jack: Перечисление перечислений - это серия сообщений в блогах, которые мне нравились. –

Смежные вопросы