0

我正在玩哈希 h1 的不存在键。但是当我看到一些错误及其解决方案时感到惊讶。我想知道递归调用如何在内部完成工作以处理错误。

第一部分

在这里尝试 h1[2][3] 导致错误。好的,在下一部分我已经解决了。

irb(main):002:0> h1=Hash.new()
=> {}
irb(main):003:0> h1[2]
=> nil
irb(main):004:0> h1[2][3]
NoMethodError: undefined method `[]' for nil:NilClass
        from (irb):4
        from C:/Ruby193/bin/irb:12:in `<main>'

第二部分

现在下面的 Hash 定义如何处理前面的错误。运行什么内部算法,这在第一部分是机器人可能的。我知道下面的 sysntx 解决了它,但我想看看内部屏幕它是如何完成工作的。

irb(main):005:0> h1 = Hash.new do |h,k|
irb(main):006:1*   h[k] = Hash.new()
irb(main):007:1> end
=> {}
irb(main):008:0> h1[2]
=> {}
irb(main):009:0> h1[2][3]
=> nil

可以修复递归调用吗?说 h1[1][2][3] 和 h1[1][2][3][4] 等等。

当我通过 h1[2] 调用 Key 时,我知道这2是我正在寻找的密钥。现在 h1[1][2] - 在这种情况下,调用用 [1][2] 寻找密钥 - 我是正确的?如果我不正确,那么真实的事情是如何从后端工作的 - 想知道这一点。

任何人都可以在这里帮助我理解吗?

谢谢,

4

2 回答 2

3
h = Hash.new{|h, k| h[k] = Hash.new(&h.default_proc)}
#demo:
p h[:a][:b][:c]=1 # =>{:a=>{:b=>{:c=>1}}}
于 2013-01-13T11:50:14.947 回答
2

如果我正确理解您的问题,我认为您可以使用递归 Proc 做您想做的事情:

p = Proc.new { Hash.new { |hash, key| hash[key] = p.call } }
h = Hash.new { |hash, key| hash[key] = p.call }

然后:

h[0][0][0] -> {}

解释:

p是一个 Ruby Proc。Procs 类似于 Ruby 块,但它是成熟的对象,因此可以存储在变量中。

Procs 可以是递归的——它们可以调用自己,我们在这个例子中利用它来创建一个新的默认哈希值,无论我们调用的哈希树有多少层。该Proc#call方法调用 Proc。请注意,Proc 的主体可以访问在其范围之外定义的变量(它是一个闭包)。

steenslags 解决方案或多或少做同样的事情,但它是一种更优雅的单行方式,利用该Hash#default_proc属性来避免定义 Proc 变量的需要。

于 2013-01-13T11:39:41.130 回答