为什么调整一个哈希值也会改变另一个值?

时间:2015-11-13 04:50:18

标签: ruby

我尝试调整密钥info的哈希"#{item} W/COUPON"的值,而不更改密钥info的{​​{1}}值,似乎无意中发生了什么。所有这些都发生在嵌套哈希中。

item

此代码运行后,

  • hash_with_coupons[item] = info hash_with_coupons[item][:count] = info[:count] - coupon_hash[:num] hash_with_coupons["#{item} W/COUPON"] = info hash_with_coupons["#{item} W/COUPON"][:price] = coupon_hash[:cost] hash_with_coupons["#{item} W/COUPON"][:count] = 1
  • hash_with_coupons[item][:price] == coupon_hash[:cost]

但它们应该分别是原价和hash_with_coupons[item][:count] == 1

1 个答案:

答案 0 :(得分:0)

您的#{item} W/COUPON条目修改item条目的原因是您已将两个info对象交给他们。也就是说,在两个键分配之后,您的哈希看起来像这样:

{
  item               => info,
  "#{item} W/COUPON" => info
}

以这种方式看待,很明显,修改一个值会修改另一个值,实际上会修改原始的info变量 - 它们都是同一个对象。让hash_with_coupons值独立的简单方法是在执行作业时在dup上致电info

hash_with_coupons[item] = info.dup
hash_with_coupons["#{item} W/COUPON"] = info.dup
# Make modifications

然后,每个哈希键都获得info副本dup执行所谓的浅拷贝,使新的Hash对象具有与旧对象相同的值。只要您的info哈希值很简单(例如Fixnum s),并且不引用要修改的更多哈希,数组等,这将起作用。否则,你需要一个deep copy,否则你会遇到你现在遇到的同样问题,只会更深一层。

由于您是新手,我建议采用不同的方法,以便更好地了解哪些值最终会在hash_with_coupons中结束。不是分配info然后修改哈希内部的内容,而是使用您想要的数据分配全新的哈希值:

hash_with_coupons[item] = {
  price: info[:price],
  count: info[:count] - coupon_hash[:num]
}
hash_with_coupons["#{item} W/COUPON"] = {
  price: info[:price] - coupon_hash[:cost],
  count: 1
}

这可以保证hash_with_coupons的值是不同的对象,因此在更改时不会意外地修改它们。它还清楚地表明哪些值最终会在哪里,因此您可以轻松查看是否再次开始共享引用。