Ruby 如何分配哈希[';a';][';b';]=';c';如果散列[';a';]没有';不存在?

Ruby 如何分配哈希[';a';][';b';]=';c';如果散列[';a';]没有';不存在?,ruby,hash,variable-assignment,autovivification,hash-of-hashes,Ruby,Hash,Variable Assignment,Autovivification,Hash Of Hashes,有比这更简单的方法吗 if hash.key?('a') hash['a']['b'] = 'c' else hash['a'] = {} hash['a']['b'] = 'c' end 一个简单的,但哈希应该是有效的哈希对象 (hash["a"] ||= {})['b'] = "c" 如果按照以下方式创建散列,默认值为新的(相同的默认值)散列:(感谢Phrogz的更正;我的语法错误) 那你就可以了 hash["a"]["b"] = "c" 无需任何附加代码。最简单的

有比这更简单的方法吗

if hash.key?('a')
  hash['a']['b'] = 'c' 
else  
  hash['a'] = {}
  hash['a']['b'] = 'c' 
end

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

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

如果按照以下方式创建
散列
,默认值为新的(相同的默认值)散列:(感谢Phrogz的更正;我的语法错误)

那你就可以了

hash["a"]["b"] = "c"
无需任何附加代码。

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

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所指出的,您可以使用以下方法使自动活跃哈希自动活跃:

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

h = Hash.new({ })
h = Hash.new(0)
这很像是这样说的:

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)
为false

然而,当你这么说的时候:

h = Hash.new({ })
h = Hash.new(0)
一切都会顺利进行,因为您永远不会在此处修改
h[k]
,您只会从
h
读取一个值(必要时将使用默认值),或为
h
指定一个新值此处的问题: 提供了一个非常有用的
AutoHash
实现

class NilClass
  def [](other)
    nil
  end
end

一旦定义了它,一切都将自动运行。但是请注意,从现在起,当用作哈希时,nil将表现为空哈希。

关键词:“ruby哈希自动活跃自动活跃”(让我们看看如何将它们链接到中——请参见“相关”)@pst:我认为存在编辑冲突-有人修复了一些拼写错误并删除了您的标记。好吧,您可以这样做,但是您的
哈希值不会改变。我想你的意思是:
hash=hash.new{h,k{h[k]=hash.new(&h.default_-proc)}
正如你所知,但可能想指出的是,这只会自动激活一个层次的深度,而这样做:
hash.new{h,k{h[k]=hash.new(&h.default_-proc)}
是海龟一直在往下走。@mu:很好的解释,但我不明白
会对所有默认条目使用完全相同的哈希值。
。我们不希望默认条目相同吗?@Radek:不,您不希望默认条目是相同的对象。如果它们使用的是同一个对象,那么你最终会发现
hash['a']
hash['b']
是同一个对象,而这甚至不会像你希望的那样出现在
hash
中。在
irb
中尝试我的示例,但是使用
Hash.new({})
构造函数,您将看到问题。
Hash.new(x)
表单只有在
x
类似于Fixnum时才有效。@Radek:And check
Hash.inspect
Hash.default.inspect
Hash['a'].inspect
Hash['b']在使用
Hash.new({})运行示例后检查
@Radek:我添加了一个更新,更好地解释了为什么
Hash.new({})
是个坏主意。与使用默认进程相比,这种方法有很大的灵活性。要构造一个默认哈希,仅当
k='a'
时,才将
h[k]
设置为
{}
,需要编写
hash.new{| |,k | k='a'?{}:nil}
,这非常难看。另一方面,表达式中的任何或所有字符串都可以是变量,因此它没有任何限制。此外,我还听说,这种方法往往比使用默认过程更快。奇怪的是,
'b'
在单引号中,而,…:-)