2017-06-15 52 views
1

初始化红宝石哈希,如:红宝石哈希初始化与each_with_object行为古怪

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

我只是想插入到一个键,但它是更新所有键的值。

+0

@SergioTulentsev你能告诉我发生了什么事吗?我只是想用具有值的键作为数组初始化散列。它创建一个散列,但后来插入,它的行为怪异,我没有得到为什么的一部分。 – jaiswal

回答

3

是的,这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] = [] } 
+2

或者说'keys.map {| k | [k,[]]} .to_h' ... –

+0

@ Md.Fhanhan:是的,这个也不错。 –

+1

'3'应该是'keys.size' – Stefan

0

您的所有密钥参考相同的数组。

简化版本,解释了这个问题:

a = [] 
b = a 
a.push('something') 
puts a #=> ['something'] 
puts b #=> ['something'] 

即使你有两个变量(ab)只有一个阵列对象。因此,对变量的参考由变量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 
-1

为什么你把它们放在一个数组中,之后你把它们放进一个散列?如果我理解正确你的问题,你可能会想这样做:

hash = {'1'=>"",'2'=>"",'3'=>""} 
hash['1'] = 'a' 
hash['2'] = 'b' 
hash['3'] = 'Hello' 

您可以在此之后将其转换为整数或任何你想要的,如果该对象的类不能满足您的要求! 希望它有帮助!

+0

你为什么认为OP想要这样做? –