【问题标题】:Hash default-value creates all of the same instance [duplicate]哈希默认值创建所有相同的实例[重复]
【发布时间】:2014-09-16 23:23:04
【问题描述】:

每当使用默认值时,我都会尝试获取嵌套散列以输出不同的散列实例。

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

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]

【问题讨论】:

  • 您遇到了什么异常?你可能想要Hash.new { Hash.new };否则,将创建一个散列并将其设置为散列的默认值。将为每个新的默认值调用块形式(并将返回一个新的哈希)。
  • 我自己的加薪是个例外。因为我希望每个实例都不同。但由于某种原因,它们不是。每个@region_data[x] 都是相同的哈希...
  • 使用指示的块形式。您现在正在创建一个散列并为每个默认值返回该散列。
  • 内联rescue 的问题之一是它们可能会掩盖您遇到的错误。将@region_data = nil[] rescue reset_region_data 更改为@region_data = nil[],我相信你会得到异常,NoMethodError: undefined method [] for nil:NilClassnil[] 毫无意义。
  • 您可能想检查例如a[10].object_id 而不是 a[10].hash - 如果我是对的,请更新您的问题,或者详细说明为什么要使用哈希方法。相同的值具有相同的hash,但这并不一定意味着它们引用的是同一个对象(尽管在您的示例中它们实际上是,请参阅我的答案)。

标签: ruby hash instance default


【解决方案1】:

如果你给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 。你的问题有点重复。

此外,正如我们在 cmets 中发现的那样,您可能想要比较 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"

【讨论】:

  • 那也行不通。但是由于某种原因用 .object_id 替换 .hash 不再引发我的“加薪”。也许我只是以某种方式使用了 object.hash 错误...
  • 你的意思是不工作?! object_id 每个对象都是唯一的。 .hash 不是(保存相同文本的两个字符串变量具有相同的哈希值,但 object_id 不同。如果更改其中一个,则更改哈希值,但不会更改 object_id)。
  • 那就是问题所在。我对 .hash 而不是 .object_id 感到困惑。带有括号的代码本身与 object_id 结合使用。
猜你喜欢
  • 2012-03-18
  • 2015-10-06
  • 1970-01-01
  • 2012-05-08
  • 1970-01-01
  • 1970-01-01
  • 2010-11-21
  • 2016-05-12
  • 1970-01-01
相关资源
最近更新 更多