使用枚举器更改ruby中的哈希值

时间:2013-03-30 03:35:44

标签: ruby hash map block

这是我的示例程序:

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中。

2 个答案:

答案 0 :(得分: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] ]转换为{{1} }}

你在做什么 - { a=>b, c=>d } - 将每个键/值对映射到一个新值并创建一个数组......然后对该数组不执行任何操作。虽然 hash.map{ … }会破坏性地改变数组,但是没有等效的Array#map!可以在一个步骤中破坏性地改变哈希。


另请注意,如果您想要破坏性地改变Hash或引用其他可变对象的任何其他对象,您可以在正常迭代期间破坏性地改变这些对象:

Hash#map!

但是,由于您在示例代码中使用了符号,因为符号可变 - 这个最终注释不会直接应用于那里。

答案 1 :(得分:1)

而不是:

w[1] = correction.chop!.to_sym

尝试直接分配哈希:

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

Ruby正在创建w数组,只是为了传递密钥和值。分配给该数组不会改变你的哈希值;它只是改变了那个临时数组。