【问题标题】:ruby hashes, why is the value getting overridden红宝石哈希,为什么值被覆盖
【发布时间】:2015-05-22 19:13:47
【问题描述】:

考虑以下代码sn-p:

inner_hash =Hash.new
 trial_hash = Hash.new
inner_hash.merge!("i_key1"=>"value1")
inner_hash.merge!("i_key2"=>"value2")
puts "inner_hash #{inner_hash}"
trial_hash.merge!("o_key1"=>inner_hash)
puts "trial_hash #{trial_hash}"
inner_hash.clear
inner_hash.merge!("i_key1"=>"value3")
inner_hash.merge!("i_key2"=>"value4")
puts "inner_hash #{inner_hash}"
trial_hash.merge!("o_key2"=>inner_hash)
puts "trial_hash #{trial_hash}"

这是打印出来的:

inner_hash {"i_key1"=>"value1", "i_key2"=>"value2"}
trial_hash {"o_key1"=>{"i_key1"=>"value1", "i_key2"=>"value2"}}
inner_hash {"i_key1"=>"value3", "i_key2"=>"value4"}
trial_hash {"o_key1"=>{"i_key1"=>"value3", "i_key2"=>"value4"}, "o_key2"=>{"i_key1"=>"value3", "i_key2"=>"value4"}}

特别是看到最后一行打印的 trial_hash。键“o_key1”的值是一个哈希值,其值应该是 value1 和 value2,但已被覆盖为 value3 和 value4。理想情况下,预期的输出应该是:

inner_hash {"i_key1"=>"value1", "i_key2"=>"value2"}
trial_hash {"o_key1"=>{"i_key1"=>"value1", "i_key2"=>"value2"}}
inner_hash {"i_key1"=>"value3", "i_key2"=>"value4"}
trial_hash {"o_key1"=>{"i_key1"=>"value1", "i_key2"=>"value2"}, "o_key2"=>{"i_key1"=>"value3", "i_key2"=>"value4"}}

为什么会观察到这种行为。我做错了什么。最初这个问题非常广泛并使用循环,出于示例目的,我已经删除并重新编写了一些行。任何帮助是极大的赞赏。谢谢

编辑:当我将 inner_hash.clear 替换为 inner_hash={}

后,问题就解决了

【问题讨论】:

    标签: ruby loops hash


    【解决方案1】:

    当你这样做时:

    trial_hash.merge!("o_key1"=>inner_hash)
    

    将inner_hash 的引用 作为值。因此,每当inner_hash 更改时,trial_hash["o_key1"] 也会相应更改,因为它们是对同一 Hash 对象的引用。

    查看他们的object_id,同样:

    trial_hash["o_key1"].object_id
    #=> 21676080
    trial_hash["o_key2"].object_id
    #=> 21676080
    inner_hash.object_id
    #=> 21676080
    

    如果使用clone,您可以获得预期的行为:

    trial_hash.merge!("o_key1"=>inner_hash.clone)
    

    【讨论】:

    • 知道了,那还有什么办法呢?
    • 令我惊讶的是,当我将代码从 inner_hash.clear 更改为 inner_hash={} 时,这并没有发生
    • @Inquisitive inner_hash={} 将使 inner_hash 成为对新 Hash 对象的引用。
    • 知道了,有什么更好的方法,使用 inner_hash ={} 或 inner_hash.clone?
    • @Inquisitive 重要的是要了解到底发生了什么。除了Hash#clear,还有其他方法可以修改Hash。例如,如果你在inner_hash 中插入一个新的键/值,如果trial_hash["o_key1"] 引用相同的Hash,它会相应地改变。
    猜你喜欢
    • 2017-04-27
    • 2012-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多