这些天我通常这样做的方式是:
h = Hash.new { |h,k| h[k] = {} }
这将为您提供一个散列,该散列创建一个新散列作为缺少键的条目,但为第二级键返回 nil:
h['foo'] -> {}
h['foo']['bar'] -> nil
您可以嵌套它以添加可以通过这种方式解决的多个层:
h = Hash.new { |h, k| h[k] = Hash.new { |hh, kk| hh[kk] = {} } }
h['bar'] -> {}
h['tar']['zar'] -> {}
h['scar']['far']['mar'] -> nil
您还可以使用以下default_proc
方法无限链接:
h = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }
h['bar'] -> {}
h['tar']['star']['par'] -> {}
上面的代码创建了一个哈希,其默认过程创建了一个具有相同默认过程的新哈希。因此,在查找未见过的键时创建为默认值的哈希将具有相同的默认行为。
编辑:更多细节
Ruby 哈希允许您控制在查找新键时如何创建默认值。指定时,此行为被封装为一个Proc
对象,并且可以通过default_proc
和default_proc=
方法访问。也可以通过将块传递给Hash.new
.
让我们稍微分解一下这段代码。这不是惯用的 ruby,但更容易将其分成多行:
1. recursive_hash = Hash.new do |h, k|
2. h[k] = Hash.new(&h.default_proc)
3. end
第 1 行将一个变量声明为recursive_hash
newHash
并开始一个块为recursive_hash
's default_proc
。该块被传递了两个对象:h
,这是Hash
正在执行键查找的实例,以及k
,正在查找的键。
第 2 行将散列中的默认值设置为新Hash
实例。这个散列的默认行为是通过传递一个Proc
从发生查找的散列创建的default_proc
;即,块本身定义的默认过程。
以下是 IRB 会话的示例:
irb(main):011:0> recursive_hash = Hash.new do |h,k|
irb(main):012:1* h[k] = Hash.new(&h.default_proc)
irb(main):013:1> end
=> {}
irb(main):014:0> recursive_hash[:foo]
=> {}
irb(main):015:0> recursive_hash
=> {:foo=>{}}
创建哈希 atrecursive_hash[:foo]
时,它default_proc
由recursive_hash
's提供default_proc
。这有两个效果:
- 的默认行为
recursive_hash[:foo]
与 相同recursive_hash
。
- 由
recursive_hash[:foo]
's创建的哈希的默认行为default_proc
将与recursive_hash
.
因此,继续 IRB,我们得到以下结果:
irb(main):016:0> recursive_hash[:foo][:bar]
=> {}
irb(main):017:0> recursive_hash
=> {:foo=>{:bar=>{}}}
irb(main):018:0> recursive_hash[:foo][:bar][:zap]
=> {}
irb(main):019:0> recursive_hash
=> {:foo=>{:bar=>{:zap=>{}}}}