Ruby Hash:为不存在的元素创建默认值

时间:2013-11-23 03:38:29

标签: ruby hash

我从这个答案here中了解到这是可能的:

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

h['bar'] # => {}
h['tar']['star']['par'] # => {}

有人可以解释它是如何运作的吗?

2 个答案:

答案 0 :(得分:11)

哈希有一个名为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,它本身也会有相同的行为,等等。{{3} }

答案 1 :(得分:1)

在此代码中,您可以按链创建哈希值,以便链的任何链接都具有相同的default_proc

因此,default_proch的{​​{1}}到目前为止都是相同的 - 它会返回h['bar']的新实例Hash