哈希默认值创建所有相同的实例

时间:2014-09-16 23:23:04

标签: ruby hash instance default

每当使用默认值时,我都会尝试使用嵌套哈希来输出不同的哈希实例。

下面的代码崩溃(我自己加注,检查实例是否相等):

def reset_region_data
  @region_data = Hash.new(Hash.new)
  # @region_data = Hash.new{ Hash.new } # Same result as the line above
  # @region_data = Hash.new { |hash,new_key|  hash[new_key] = {} }  # Same problem as the above lines.
end

def foo
  reset_region_data
  raise if @region_data[0].hash == @region_data[1 * 50 + 1].hash # <<<<< crashes
end

foo

这很奇怪。所以哈希默认为所有相同的实例?但为什么呢?

但是这段代码没有:

a = Hash.new(Hash.new())

a[10][10] = 1
a[11][11] = 2

raise if a[10][10].hash == a[11][11].hash
p a[10][10]

此代码也不会崩溃:

a = Hash.new(Hash.new())

a[10] = 1
a[11] = 2

raise if a[10].hash == a[11].hash
p a[10]

1 个答案:

答案 0 :(得分:2)

如果你给Hash.new一个对象(比如另一个Hash.new),那么这个对象就是默认值。它是共享跨不同的密钥。

default = []
hash = Hash.new(default)
hash[:one] << 1
# now default is [1] !

您希望将Hash.new与块一起使用,以便每次找不到密钥时都会发生新的事情。

h = Hash.new { |hash,new_key|  hash[new_key] = {} }

有很好的解释,例如在Ruby hash default value behavior。你的问题有点重复。

另外,正如我们在评论中指出的那样,您可能希望比较object_id而不是hash值。

first_hash = {}
second_hash = {}

# .hash same, but different objects!
puts "initial, hash:"
puts first_hash.hash == second_hash.hash ? " - same" : " - differs"
puts "initial, object_id"
puts first_hash.object_id == second_hash.object_id ? " - same" : " - differs"
puts

# Change the world
# .hash different, and still different objects.
first_hash[:for] = "better"
puts "better world now, hash:"
puts first_hash.hash == second_hash.hash ? " - same" : " - differs"
puts "better world now, object_id"
puts first_hash.object_id == second_hash.object_id ? " - same" : " - differs"