2013-03-30 2 views
2

Вот мой пример программы:Изменение хэша в рубин, используя перечислитель

what = {:banana=>:fruit, :pear=>:fruit, :sandal=>:fruit, :panda=>:fruit, :apple=>:fruit} 

what.map do |w| 
    p "is this right?" 
    awesome_print w 
    fix = gets 
    fix.chop! 
    if (fix == "N") 
     p "Tell me what it should be" 
     correction = gets 
     w[1] = correction.chop!.to_sym 
    end 
    p w 
end 

Я бегу, и я получаю это (мой вход включен):

"is this right?" 
[ 
    [0] :banana, 
    [1] :fruit 
] 
Y 
[:banana, :fruit] 
"is this right?" 
[ 
    [0] :pear, 
    [1] :fruit 
] 
Y 
[:pear, :fruit] 
"is this right?" 
[ 
    [0] :sandal, 
    [1] :fruit 
] 
N 
"Tell me what it should be" 
footwear 
[:sandal, :footwear] 
"is this right?" 
[ 
    [0] :panda, 
    [1] :fruit 
] 
N 
"Tell me what it should be" 
animal 
[:panda, :animal] 
"is this right?" 
[ 
    [0] :apple, 
    [1] :fruit 
] 
Y 
[:apple, :fruit] 
=> [[:banana, :fruit], [:pear, :fruit], [:sandal, :footwear], [:panda, :animal], [:apple, :fruit]] 
>> what 
=> {:banana=>:fruit, :pear=>:fruit, :sandal=>:fruit, :panda=>:fruit, :apple=>:fruit} 

Мой вопрос, как может Я меняю Хеш? irb сообщает мне, когда я запускаю программу, которую обрабатывает каждый перечислимый элемент, но результаты не сохраняются в моем хеше what.

ответ

5

Если вы хотите, чтобы мутировать хэш на месте (как вы, кажется, хотите), просто сделать это:

my_hash.each do |key,value|  # map would work just as well, but not needed 
    my_hash[key] = some_new_value  
end 

Если вы хотите создать новый хэш, без изменения оригинала:

new_hash = Hash[ my_hash.map do |key,value| 
    [ key, new_value ] 
end ] 

Как это работает в том, что Enumerable#map возвращает массив (в данном случае массив пар ключ/значение из двух элементов), и Hash.[] может превратиться в [ [a,b], [c,d] ]{ a=>b, c=>d }.

Что вы делали - hash.map{ … } - сопоставлял каждую пару ключ/значение новому значению и создавал массив ... а затем ничего не делал с этим массивом. Хотя там isArray#map!, который разрушит массив на месте, нет эквивалента Hash#map!, чтобы разрушить хеш за один шаг.


Заметим также, что если вы хотите, чтобы с разрушением мутировать хэша или любой другой объект, который ссылается на другие изменяемые объекты-на месте вы можете просто деструктивно мутировать эти объекты во время нормальной итерации:

# A simple hash with mutable strings as values (not symbols) 
h = { a:"zeroth", b:"first", c:"second", d:"third" } 

# Mutate each string value 
h.each.with_index{ |(char,str),index| str[0..-3] = index.to_s } 

p h #=> {:a=>"0th", :b=>"1st", :c=>"2nd", :d=>"3rd"} 

Однако , так как вы используете символы для значений в вашем примере кода, а так как символы не mutable - это последнее примечание прямо не применяется.

1

Вместо:

w[1] = correction.chop!.to_sym 

Попробуйте назначить для хэша непосредственно:

what[w[0]] = correction.chop!.to_sym 

Рубин создает что w массив просто передать вам ключ и значение. Присвоение этому массиву не изменит ваш хэш; это только изменение этого временного массива.

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