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

时间:2011-05-04 04:26:15

标签: ruby hash variable-assignment autovivification hash-of-hashes

有没有比

更简单的方法
if hash.key?('a')
  hash['a']['b'] = 'c' 
else  
  hash['a'] = {}
  hash['a']['b'] = 'c' 
end

5 个答案:

答案 0 :(得分:39)

最简单的方法是使用块参数construct your 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}}"

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

hash = Hash.new({ })

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

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

hash = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }

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

h = Hash.new({ })

这就像说:

h = Hash.new
h.default = { }

然后,当您访问h以将内容指定为h[:k][:m] = y时,其行为就像您执行此操作一样:

if(h.has_key?(:k))
    h[:k][:m] = y
else
    h.default[:m] = y
end

然后,如果您h[:k2][:n] = z,您最终会分配h.default[:n] = z。请注意,h仍然表示h.has_key?(:k)为假。

然而,当你这样说:

h = Hash.new(0)

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

答案 1 :(得分:10)

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

(hash["a"] ||= {})['b'] = "c"

答案 2 :(得分:2)

如果您创建hash如下所示,默认值为新的(默认值相同)散列:(感谢Phrogz进行更正;我的语法错误)

hash = Hash.new{ |h,k| h[k] = Hash.new(&h.default_proc) }

然后你可以做

hash["a"]["b"] = "c"

没有任何额外的代码。

答案 3 :(得分:0)

这里的问题: Is auto-initialization of multi-dimensional hash array possible in Ruby, as it is in PHP? 提供了一个非常有用的AutoHash实现,可以做到这一点。

答案 4 :(得分:0)

class NilClass
  def [](other)
    nil
  end
end

一旦你定义了,一切都会自动生效。但请注意,从现在开始nil在用作哈希时会表现为空哈希。