初始化Ruby Hash,就像:
keys = [0, 1, 2]
hash = Hash[keys.each_with_object([]).to_a]
尝试将值插入键时行为异常。
hash[0].push('a')
# will result into following hash:
=> {0=>["a"], 1=>["a"], 2=>["a"]}
我只是想插入一个键,但它正在更新所有键的值。
是的,这个each_with_object
本身就非常奇怪。这不是应该如何使用它。问题正是因为你误用了它。
keys.each_with_object([]).to_a
# => [[0, []], [1, []], [2, []]]
你看,即使看起来这些数组是分开的,但在所有三种情况下它实际上是同一个数组。这就是为什么如果你把一个元素推入一个元素,它就会出现在所有其他元素中。
这里有一个更好的方法:
h = keys.each_with_object({}) {|key, h| h[key] = []}
# => {0=>[], 1=>[], 2=>[]}
或者,说
h = keys.zip(Array.new(keys.size) { [] }).to_h
或者其他一些方式。
如果您不关心哈希具有这组确切的键,而只是希望所有键都具有空数组作为默认值,那也是可能的。
h = Hash.new { |hash, key| hash[key] = [] }
所有键都引用同一个数组。
解释问题的简化版本:
a = []
b = a
a.push('something')
puts a #=> ['something']
puts b #=> ['something']
即使你有两个变量(a
和b
(,也只有一个数组对象。因此,对变量 a
引用的数组的任何更改也会更改变量 b
引用的数组。因为它是同一个对象。
您要实现的目标的长版本将是:
keys = [1, 2, 3]
hash = {}
keys.each do |key|
hash[key] = []
end
还有一个更短的版本:
[1, 2 ,3].each_with_object({}) do |key, accu|
accu[key] = []
end