1

我正在尝试创建一个Hash-es Hash。第二级散列的值是一个默认为0的整数。我要做的是从一个空的散列散列开始,然后当我添加一个值时,如果键不存在,它们的键应该被添加具有默认值。

Hash当我用一个简单的整数尝试这个时,它工作正常:

irb(main):003:0> h = Hash.new(0)
=> {}
irb(main):004:0> h[1] += 1
=> 1
irb(main):005:0> p h
{1=>1}
=> nil
irb(main):006:0> h.keys.size
=> 1
irb(main):007:0>

h现在有一个键,值为 1。完美。

但是当我的哈希值是哈希时,它似乎不起作用:

irb(main):007:0> h = Hash.new(Hash.new(0))
=> {}
irb(main):008:0> h[1][1] += 1
=> 1
irb(main):009:0> p h
{}
=> nil
irb(main):010:0> h.keys.size
=> 0
irb(main):011:0>

我做错了什么,或者我不能将哈希的默认值设置为Hash.new(0)

编辑:

根据下面的答案,我能够弄清楚我做错了什么。实际上,我能够找出我的想法错误的地方。长话短说,h[1][1]不嵌套Hash.new调用,除非你给Hash.new一个代码块来调用。表达式的值h[1][1] += 1符合1预期,但只有最里面的哈希被正确初始化。

我发布这个是因为虽然我上面的示例使用了 2 维散列,但我的实际问题使用了 3 维散列:

syms[level][exchange][symbol] = count

该解决方案可能对遇到此问题的其他人有所帮助,因此以下代码可以按照我想要的方式进行工作:

irb(main):024:0> syms = Hash.new{|h1,k1| h1[k1] = Hash.new{|h2,k2| h2[k2] = Hash.new(0)}}
=> {}
irb(main):026:0> syms["level1"]["NYSE"]["IBM"] += 1
=> 1
irb(main):027:0> p syms
{"level1"=>{"NYSE"=>{"IBM"=>1}}}
=> nil
irb(main):028:0>
4

2 回答 2

4

创建 Hash 时设置默认值的最常用方法是使用带有块参数的 Hash#new 函数:

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

您遇到的问题是您将默认设置为对象指针而不是要执行的一段代码。也就是说,每次访问“外部”哈希中的缺失值时,它都会返回一个指向完全相同对象的指针。为了向自己证明这一点,试试这个:

>> h = Hash.new(Hash.new(0))
=> {}
>> h[1] === h[2]
=> true

因此,您实际上可以为哈希设置默认值,但这样做不会达到您想要的效果。递增 h[1][1] 实际上会更改默认哈希本身,因为 h[1] 尚未初始化。

希望这可以帮助。

于 2010-08-26T14:39:16.600 回答
4
h = Hash.new(Hash.new(0))

Hash.new(0) 是默认对象;对于每个不存在的键,它都是同一个对象。这只是当密钥不存在时哈希返回的内容。

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

{|h,k| h[k]=Hash.new(0)} 是默认的 Proc。它在密钥不存在时运行,并为每个不存在的密钥创建一个的哈希(默认为 0)。

于 2010-08-26T14:42:38.837 回答