Ruby Hash:为不存在的元素创建默认值
我在这里从这个答案中了解到这是可能的:
h = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) } h['bar'] # => {} h['tar']['star']['par'] # => {}
有人能解释它是如何工作的吗?
哈希有一个叫做default_proc
的东西,它只是当你试图访问一个不存在的哈希键时Ruby运行的一个proc。 此proc接收散列本身和目标键作为参数。
您可以随时设置哈希的default_proc
。 将块参数传递给Hash.new
只是允许您初始化哈希并在一个步骤中设置其default_proc
:
h = Hash.new h.default_proc = proc{ |hash, key| hash[key] = 'foo' } # The above is equivalent to: h = Hash.new{ |hash, key| hash[key] = 'foo' }
我们还可以通过调用h.default_proc
来访问哈希的默认proc。 知道这一点,并且知道&符号( &
)允许作为普通参数传递的proc被视为块参数,我们现在可以解释这段代码是如何工作的:
cool_hash = Hash.new{ |h, k| h[k] = Hash.new(&h.default_proc) }
当我们尝试访问不存在的密钥时,将调用传递给Hash.new
的块。 该块将接收哈希本身作为h
,并且我们尝试访问的密钥为k
。 我们通过将h[k]
(即我们尝试访问的密钥的值)设置为新哈希来进行响应。 在这个新哈希的构造函数中,我们传递“父”哈希的default_proc
,使用&符号强制它被解释为块参数。 这相当于执行以下操作,达到无限深度:
cool_hash = Hash.new{ |h, k| h[k] = Hash.new{ |h, k| h[k] = Hash.new{ ... } } }
最终的结果是我们尝试访问的密钥被初始化为一个新的Hash,它本身会将任何“未找到”的密钥初始化为一个新的Hash,它本身也会有相同的行为,等等。 它一直是哈希。
在此代码中,您可以按链创建哈希,以便链的任何链接都具有相同的default_proc
所以, h
和h['bar']
default_proc
和目前为止是相同的 – 它将使用此default_proc
返回Hash
新实例