我尝试了以下ruby代码,我认为这会将字长的哈希返回到具有这些长度的单词。相反它是空的。
map = Hash.new(Array.new)
strings = ["abc","def","four","five"]
strings.each do |word|
map[word.length] << word
end
但是,如果我将其修改为
map = Hash.new
strings = ["abc","def","four","five"]
strings.each do |word|
map[word.length] ||= []
map[word.length] << word
end
确实有效。
第一个版本是不是只创建了一个默认值为空数组的哈希值?在这种情况下,我不明白为什么2个块给出不同的值。
答案 0 :(得分:27)
问题是你实际上没有为散列键分配任何东西,你只是使用<<
运算符来修改默认值的现有内容。由于您没有为散列键指定任何内容,因此不会添加任何内容。实际上,您会注意到默认值是修改后的值:
h = Hash.new []
p h[0] # []
h[0] << "Hello"
p h # {}
p h[0] # ["Hello"]
p h[1] # ["Hello"]
这是因为相同的Array
对象被维护为默认值。您可以使用+
运算符对其进行修复,但效率可能较低:
map = Hash.new []
strings = ["abc", "def", "four", "five"]
strings.each do |word|
map[word.length] += [word]
end
现在它按预期工作。
答案 1 :(得分:11)
无论如何,您应该使用Enumerable#group_by:
["abc", "def", "four", "five"].group_by(&:length)
#=> {3=>["abc", "def"], 4=>["four", "five"]}
答案 2 :(得分:2)
我认为第一个版本的真正含义是默认值只是一个数组。第二个示例显式创建一个新数组(如果尚不存在)。
这对于进一步clarify来说是一个很好的阅读。