我在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"]}
答案 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以下解释。)
如果您给它一个块,它会调用该块,每次都对一个不存在的哈希条目进行查找。所以你不只是创建一个数组了。您正在为哈希的每个条目创建一个。