运行 Hash.new([]) 做你期望的,但不是你期望的方式

Running Hash.new([]) does what you expect but not in the way you expect it

所以,我想创建一个散列,其中任何键都变成数组,而无需单独声明它们。

因此我使用

foo = Hash.new([])
=> {}

然后我可以将项目添加到之前未声明的键中

foo[:bar] << 'Item 1'
=> ['Item 1']

这样做有点奇怪。当我打电话时

foo
=> {}

查看hash,是空的。连运行宁

foo.keys
=> []

显示它是空的。 但是,如果我 运行

foo[:bar]
=> ['Item 1']

请理解。

foo = Hash.new([]) 将不存在的键的默认值设置为数组。这里 foo[:bar] << 'Item 1' :bar 键不存在,因此 foo 使用一个数组,您可以向其中添加一个新元素。这样做会改变默认值,因为数组是通过引用提供给您的。


> foo = Hash.new([])
=> {}
> foo.default
=> []

如果您在哈希上调用任何未定义的键,您将得到这个数组:

> foo[:bar] << 'Item 1'
=> ["Item 1"] 
> foo[:foo]
=> ["Item 1"]

为了实现您的目标,您每次都应该 return 一个新数组。可以通过将块传递给 Hash.new,每次访问未定义的键时都会执行该块:

> foo = Hash.new { |hash, key| hash[key] = [] }
=> {}
> foo[:bar] << 'Item 1'
=> ["Item 1"]
> foo[:bar]
=> ["Item 1"]
> foo.keys
=> [:bar]
> foo[:foo]
=> []
> foo[:foo] << 'Item 2'
=> ["Item 2"]
> foo
=> {:bar=>["Item 1"], :foo=>["Item 2"]}

Here is the documentation.