哈希默认值是具有相同默认值的哈希。

3

像这样设置哈希值的默认值:

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

当访问一个未知的键时,它会创建(并分配)一个新的哈希表,但是对于创建的哈希表中的未知键,它会返回nil

hash[:unkown_key] #=> {}
hash[:unkown_key][:nested_unknown] #=> nil

我可以这样让它在第二层级别上运行:
hash = Hash.new do |hsh, key|
  hsh[key] = Hash.new { |nest_hsh, nest_key| nest_hsh[nest_key] = {} }
end

但是,在第三层级别它不起作用:
hash[:unkown_key][:nested_unknown] #=> {}
hash[:unkown_key][:nested_unknown][:third_level] #=> nil

如何使其在任意级别上运作?

hash[:unkown_key][:nested_unknown][:third_level][...][:nth_level] #=> {}

一个任意大的数(你似乎是这个意思)并不是无穷大(事实上,无穷大甚至不是一个普通意义下的数字,除非你在谈论亚伯拉罕·罗宾逊的非标准分析)。你似乎把它们混淆了(我在这个网站上看到太多混淆它们的用户)。 - sawa
1
请不要太字面理解我的“无穷大” - 当然这只是夸张的说法,强调我的问题。我不想让数学家为此费太多心思,如果我有所冒犯,请谅解。 - Markus
哦,顺便说一下,:infinity 是一个符号,不是一个数字;-) - Markus
你不是想表达有无限多个级别吗(这实际上与你的真实意图相反)? - sawa
2
@Markus,我已经将:infinity替换为:nth_level,希望这样更清晰明了。 - Stefan
1
我想说哈希真的非常嵌套,使用“无穷大”作为夸张。我认为字面上的无限层不可能(会消耗大量内存 - 无限量的内存?;-))。感谢上帝@Stefan为我们澄清了这一点;-) - Markus
3个回答

6

有点令人费解,但是你可以将哈希表的default_proc传递给内部哈希表:

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

hash[:foo] #=> {}
hash[:foo][:bar] #=> {}
hash[:foo][:bar][:baz] #=> {}

hash #=> {:foo=>{:bar=>{:baz=>{}}}}

谢谢,这看起来对我来说是最干净的解决方案! - Markus

3
bottomless_hash = ->() do
  Hash.new { |h, k| h[k] = bottomless_hash.call }
end

hash = bottomless_hash.call
hash[:unkown_key][:nested_unknown][:third_level][:fourth] # => {}

2
你可以使用递归创建一个 method 来实现这个功能。
class Hash
  def self.recursive
    new { |hash, key| hash[key] = recursive }
  end
end

hash = Hash.recursive
hash[:unknown_key] # => {}
hash[:first_unknown_key][:second_unknown_key][...][:infinity]
# hash => {first_unknown_key:  {second_unknown_key: {... {infinity: {}}}}}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接