对于具有默认值的Ruby哈希,这是正确的行为吗?

时间:2012-04-28 13:21:03

标签: ruby

hash = Hash.new(Hash.new([]))
hash[1][2] << 3

hash[1][2] # => [3]
hash # => {}
hash.keys # => []
hash.values # => []

发生了什么事? Ruby的隐藏数据(1.9.3p125)

3 个答案:

答案 0 :(得分:4)

  

发生了什么事? Ruby的隐藏数据(1.9.3p125)

Ruby既不隐藏数据也不隐藏docs

只要在哈希中找不到密钥,就会返回传递给Hash构造函数的默认值。但是这个默认值实际上从未实际存储在哈希中。

要获得您想要的内容,您应该使用带有块的Hash构造函数并将自己的默认值存储到哈希中(在嵌套哈希的两个级别上):

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

hash[1][2] << 3

p hash[1][2]  #=> [3]
p hash        #=> {1=>{2=>[3]}}
p hash.keys   #=> [1]
p hash.values #=> [{2=>[3]}]

答案 1 :(得分:1)

这很简单。如果将对象传递给Hash构造函数,它将成为该哈希中所有缺失键的默认值。有趣的是,这个值是可变的。观察:

hash = Hash.new(Hash.new([]))
# mutate default value for nested hash
hash[1][2] << 3

# default value in action
hash[1][2] # => [3]
# and again
hash[1][3] # => [3]
# and again
hash[1][4] # => [3]

# set a plain hash (without default value)
hash[1] = {}

# what? Where did my [3] go?
hash[1][2] # => nil

# ah, here it is!
hash[2][3] # => [3]

答案 2 :(得分:0)

我在irb中尝试了这个。 Seams Ruby不会将元素标记为“可见”,除非通过=显式地影响默认值。例如。

hash = Hash.new(Hash.new([]))
hash[1] = Hash.new([])
hash[1][2] = [3]
hash
#=> {1=>{2=>[3]}}

可能是一些安装者错过了这种“不理智”的行为......