Ruby哈希用每个_初始化,而_对象的行为异常

Ruby哈希用每个_初始化,而_对象的行为异常,ruby,hash,Ruby,Hash,初始化Ruby哈希,如: 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"]} 我只是尝试插入一个键,但它正在更新所有键的值。您的所有键引用同一数组 解释问题的简化版本: a = [] b = a a.

初始化Ruby哈希,如:

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"]}

我只是尝试插入一个键,但它正在更新所有键的值。

您的所有键引用同一数组

解释问题的简化版本:

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

是的,
每一个带有对象的对象本身都非常奇怪。这不是它应该被使用的方式。而问题的出现恰恰是因为你误用了它

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
或者其他一些方式

如果您不关心hash是否具有这组精确的键,而只是希望all键具有空数组作为默认值,那么这也是可能的

 h = Hash.new { |hash, key| hash[key] = [] }

@塞吉奥图兰采夫,你能告诉我发生了什么事吗?我只是想初始化一个散列,其中键的值作为数组。它创建了一个散列,但后来随着插入,它的行为很奇怪,我不明白为什么。那
3
应该是
键。大小
一如既往,当你想知道为什么会有一大群克隆时,请检查
object\u id