我正在向哈希键添加项目。我期待得到这样的结构:
{
'a' : [1],
'b' : [2, 3, 4]
}
我使用了一个数组来初始化哈希。
irb> hash = Hash.new([])
=> {}
然后开始使用它:
irb> hash['a'] << 1
=> [1]
irb> hash['b'] << 2
=> [1, 2]
但事实证明:
irb> hash
=> {}
答案 0 :(得分:11)
请尝试以下方法:
hash = Hash.new{|h, k| h[k] = []}
hash['a'] << 1 # => [1]
hash['b'] << 2 # => [2]
您获得意外结果的原因是您将空数组指定为默认值,但使用了相同的数组;没有复制。正确的方法是使用新的空数组初始化值,就像我的代码一样。
答案 1 :(得分:4)
您使用constructor存储[]
作为访问未知密钥时返回的默认值。由于Array#<<
修改其接收器到位,这个最初为空的数组会增长。
更详细地解释:
执行hash['a'] << 1
时会发生这种情况:
hash
查看是否存在名为'a'
Hash.new([])
构建了它,因此确实有[]
这样的值,并返回该值。[] << 1
被评估,这意味着哈希现在存储[1]
作为在请求先前未被发现的密钥时返回的值。如果您想要存储键值对,请使用带有块的构造函数的第三种形式:
hash = Hash.new{|h, key| h[key] = []}
答案 2 :(得分:2)
hash['a'] << 1
和hash['b'] << 2
不是创建键/值对的正确语法。您必须使用=
:
hash['a'] = []
hash['a'] << 1
hash['b'] = []
hash['b'] << 2
那应该给你哈希{'a' : [1], 'b' : [2]}
答案 3 :(得分:1)
这是完全您期望看到的行为。
您永远不会向Hash
添加任何内容,因此Hash
完全为空。当您查找某个键时,该键将永远不存在,因此它将返回默认值,您指定该值为Array
。
因此,您查找不存在的键'a'
,从而返回您指定为默认值的Array
。然后,您在<<
上致电Array
,向其附加值(1
)。
接下来,您查找也不存在的键'b'
,从而返回您指定为默认值的Array
,现在包含元素1
您之前补充说。然后,您在<<
上致电Array
,并将值2
附加到其中。
你最终得到的Hash
仍然是空的,因为你从来没有添加任何东西。 Hash
的默认值现在是一个包含值1
和2
的数组。
您看到的输出是因为IRb始终打印已评估的最后一个表达式的结果。示例中的最后一个表达式是<<
上的Array
。 <<
返回其接收器,然后是整个表达式的返回值,因此IRb打印出来。