0

我在 IRB 1.8.7 中看到一些带有打印哈希的奇怪行为。如果我用 a 初始化我的散列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"]}
4

2 回答 2

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"]

散列本身仍然是空的——你没有给它分配任何东西。数据不存在于散列中 - 它存在于为散列中缺少键返回的数组中。

于 2013-09-25T23:55:25.333 回答
1

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

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

你的版本对我来说也不能正常工作。理解起来有点复杂的原因。从文档:

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

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

您指定的obj[],它只是一个默认值。它实际上并未将散列的内容设置为该默认值。因此,当您这样做时h["blah"] << "test",您实际上只是要求它返回默认值的副本,然后添加"test"到该副本。它根本不会进入散列。(我需要感谢 Chris Heald 在下面解释这一点。)

相反,如果您给它一个块,它会在您每次查找不存在的哈希条目时调用该块。因此,您不再只是创建一个数组。您正在为哈希的每个条目创建一个。

于 2013-09-25T23:49:43.560 回答