如果hash ['a']不存在,如何分配hash ['a'] ['b'] ='c'?

Rad*_*dek 21 ruby hash variable-assignment autovivification hash-of-hashes

有什么比这简单的方法

if hash.key?('a')
  hash['a']['b'] = 'c' 
else  
  hash['a'] = {}
  hash['a']['b'] = 'c' 
end
Run Code Online (Sandbox Code Playgroud)

mu *_*ort 39

最简单的方法是使用块参数构造Hash:

hash = Hash.new { |h, k| h[k] = { } }
hash['a']['b'] = 1
hash['a']['c'] = 1
hash['b']['c'] = 1
puts hash.inspect
# "{"a"=>{"b"=>1, "c"=>1}, "b"=>{"c"=>1}}"
Run Code Online (Sandbox Code Playgroud)

此表单用于new创建新的空哈希值作为默认值.你不想要这个:

hash = Hash.new({ })
Run Code Online (Sandbox Code Playgroud)

因为它将对所有默认条目使用完全相同的哈希.

另外,正如Phrogz所说,你可以使用以下命令使自动生成的哈希自动生成default_proc:

hash = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }
Run Code Online (Sandbox Code Playgroud)

更新:我想我应该澄清我的警告Hash.new({ }).当你这样说:

h = Hash.new({ })
Run Code Online (Sandbox Code Playgroud)

这就像说:

h = Hash.new
h.default = { }
Run Code Online (Sandbox Code Playgroud)

然后,当您访问h分配内容时h[:k][:m] = y,它的行为就像您这样做:

if(h.has_key?(:k))
    h[:k][:m] = y
else
    h.default[:m] = y
end
Run Code Online (Sandbox Code Playgroud)

然后,如果你h[:k2][:n] = z,你最终会分配h.default[:n] = z.请注意,h仍然说这h.has_key?(:k)是假的.

但是,当你这样说时:

h = Hash.new(0)
Run Code Online (Sandbox Code Playgroud)

一切都会好起来因为你永远不会h[k]在这里进行修改,你只会读取一个值h(必要时将使用默认值)或为其分配一个新值h.

  • 如你所知,但可能想要指出的是,只有自动生成一个级别,而这样做:`Hash.new {| h,k | h [k] = Hash.new(&h.default_proc)}`一直是乌龟. (11认同)

Nar*_*iya 10

一个简单的,但哈希应该是一个有效的哈希对象

(hash["a"] ||= {})['b'] = "c"
Run Code Online (Sandbox Code Playgroud)