ruby 添加到带有数组值的哈希
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11589269/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ruby adding to hash with array value
提问by Jeff Storey
I tried the following ruby code, which I thought would return a hash of word lengths to the words with those lengths. Instead it is empty.
我尝试了以下 ruby 代码,我认为它会将单词长度的散列返回到具有这些长度的单词。相反,它是空的。
map = Hash.new(Array.new)
strings = ["abc","def","four","five"]
strings.each do |word|
map[word.length] << word
end
However, if I modify it to
但是,如果我将其修改为
map = Hash.new
strings = ["abc","def","four","five"]
strings.each do |word|
map[word.length] ||= []
map[word.length] << word
end
It does work.
它确实有效。
Doesn't the first version just create a hash whose default values are an empty array? In this case, I don't understand why the 2 blocks give different values.
第一个版本不只是创建一个默认值为空数组的哈希吗?在这种情况下,我不明白为什么 2 个块给出不同的值。
回答by Ry-
The problem is that you aren't actually assigning anything to the hash keys, you're just using the <<operator to modify the existing contents of a default value. Since you don't assign anything to the hash key, it is not added. In fact, you'll notice the default value is the one modified:
问题是您实际上并没有为散列键分配任何内容,您只是使用<<运算符来修改默认值的现有内容。由于您没有为散列键分配任何内容,因此不会添加任何内容。事实上,您会注意到默认值是修改后的值:
h = Hash.new []
p h[0] # []
h[0] << "Hello"
p h # {}
p h[0] # ["Hello"]
p h[1] # ["Hello"]
This is because the same Arrayobject is maintained as the default value. You can fix it by using the +operator, though it may be less efficient:
这是因为相同的Array对象被维护为默认值。您可以使用+运算符修复它,尽管它可能效率较低:
map = Hash.new []
strings = ["abc", "def", "four", "five"]
strings.each do |word|
map[word.length] += [word]
end
And now it works as expected.
现在它按预期工作。
回答by tokland
In any case, you should use Enumerable#group_by:
在任何情况下,您都应该使用Enumerable#group_by:
["abc", "def", "four", "five"].group_by(&:length)
#=> {3=>["abc", "def"], 4=>["four", "five"]}

