IRB(显然)没有正确检查哈希

时间:2013-09-25 22:56:58

标签: ruby hash irb

我在IRB 1.8.7中看到了一些带有打印哈希值的奇怪行为。如果我使用Hash.new初始化我的哈希值,则表明我的哈希值正在“评估”为空哈希:

irb(main):024:0> h = Hash.new([])
=> {}
irb(main):025:0> h["test"]
=> []                                                        
irb(main):026:0> h["test"] << "blah"                    
=> ["blah"]                                         
irb(main):027:0> h                              
=> {}                                                  
irb(main):028:0> puts h.inspect                       
{}                                                               
=> nil                 
irb(main):031:0> require 'pp'     
=> true                           
irb(main):032:0> pp h             
{}                                
=> nil                            
irb(main):033:0> h["test"]
=> ["blah"]

如您所见,数据 实际存在于散列中,但尝试打印或显示它似乎失败了。使用哈希文字初始化似乎可以解决这个问题:

irb(main):050:0> hash = { 'test' => ['testval'] }
=> {"test"=>["testval"]}
irb(main):051:0> hash
=> {"test"=>["testval"]}
irb(main):053:0> hash['othertest'] = ['secondval']
=> ["secondval"]
irb(main):054:0> hash
=> {"othertest"=>["secondval"], "test"=>["testval"]}

2 个答案:

答案 0 :(得分:4)

这里的问题是调用h["test"]实际上并没有在哈希中插入新密钥 - 它只返回默认值,即传递给Hash.new的数组。

1.8.7 :010 > a = []
 => []
1.8.7 :011 > a.object_id
 => 70338238506580
1.8.7 :012 > h = Hash.new(a)
 => {}
1.8.7 :013 > h["test"].object_id
 => 70338238506580
1.8.7 :014 > h["test"] << "blah"
 => ["blah"]
1.8.7 :015 > h.keys
 => []
1.8.7 :016 > h["bogus"]
 => ["blah"]
1.8.7 :017 > h["bogus"].object_id
 => 70338238506580
1.8.7 :019 > a
 => ["blah"]

散列本身仍为空 - 您尚未为其分配任何内容。散列中不存在数据 - 它存在于为散列中的缺失键返回的数组中。

答案 1 :(得分:1)

看起来你正在尝试创建一个数组哈希。为此,我建议你这样初始化:

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

您的版本也无法正常使用。之所以理解起来有点复杂。 From the docs:

  

如果指定了 obj ,则单个对象将用于所有默认值

我添加了粗体。其余的重点是原样。

您指定obj[],并且它只是默认值。它实际上并没有哈希的内容设置为该默认值。因此,当您执行h["blah"] << "test"时,您实际上只是要求它返回默认值的副本,然后将"test"添加到该副本。它根本不会进入哈希。 (我需要给Chris Heald以下解释。)

如果您给它一个块,它会调用该块,每次都对一个不存在的哈希条目进行查找。所以你不只是创建一个数组了。您正在为哈希的每个条目创建一个。