Ruby my_hash.key==[],但my_hash[key]给出了一个值?
我试图演示一种情况,在创建散列时,为了设置给定键的默认值,有必要将块传递给Ruby my_hash.key==[],但my_hash[key]给出了一个值?,ruby,hash,Ruby,Hash,我试图演示一种情况,在创建散列时,为了设置给定键的默认值,有必要将块传递给Hash.new 为了显示可能出现的错误,我创建了以下代码,它将单个值作为参数传递给Hash.new。我希望所有外部散列键最终都持有对同一内部散列的引用,从而导致“堆”的计数混合在一起。事实上,这似乎确实发生了。但是part\u计数。每个似乎没有找到任何要迭代的键/值,并且part\u计数。键返回一个空数组。只有part\u计数[0]和part\u计数[1]为我成功检索到一个值 piles = [ [:gear, :s
Hash.new
为了显示可能出现的错误,我创建了以下代码,它将单个值作为参数传递给Hash.new
。我希望所有外部散列键最终都持有对同一内部散列的引用,从而导致“堆”的计数混合在一起。事实上,这似乎确实发生了。但是part\u计数。每个似乎没有找到任何要迭代的键/值,并且part\u计数。键返回一个空数组。只有part\u计数[0]
和part\u计数[1]
为我成功检索到一个值
piles = [
[:gear, :spring, :gear],
[:axle, :gear, :spring],
]
# I do realize this should be:
# Hash.new {|h, k| h[k] = Hash.new(0)}
part_counts = Hash.new(Hash.new(0))
piles.each_with_index do |pile, pile_index|
pile.each do |part|
part_counts[pile_index][part] += 1
end
end
p part_counts # => {}
p part_counts.keys # => []
# The next line prints no output
part_counts.each { |key, value| p key, value }
p part_counts[0] # => {:gear=>3, :spring=>2, :axle=>1}
对于上下文,下面是我打算在“断开”代码之后显示的更正代码。part_counts
中每个桩的零件应按原样分开每个
和键
也按预期工作
# ...same pile initialization code as above...
part_counts = Hash.new {|h, k| h[k] = Hash.new(0)}
# ...same part counting code as above...
p part_counts # => {0=>{:gear=>2, :spring=>1}, 1=>{:axle=>1, :gear=>1, :spring=>1}}
p part_counts.keys # => [0, 1]
# The next line of code prints:
# 0
# {:gear=>2, :spring=>1}
# 1
# {:axle=>1, :gear=>1, :spring=>1}
part_counts.each { |key, value| p key, value }
p part_counts[0] # => {:gear=>2, :spring=>1}
但是为什么在第一个示例中,每个
和键都不起作用呢?给定给哈希的值。new
用作默认值,但该值不会插入哈希中。因此,part\u count
保持为空。您可以使用part\u count[…]
获得默认值,但这对哈希没有影响,它实际上不包含密钥
当调用part\u counts[pile\u index][part]+=1
时,part\u counts[pile\u index]
返回默认值,并使用赋值修改该值,而不是part\u counts
你有这样的想法:
outer = Hash.new({})
outer[1][2] = 3
p outer, outer[1]
也可以这样写:
inner = {}
outer = Hash.new(inner)
inner2 = outer[1] # inner2 refers to the same object as inner, outer is not modified
inner2[2] = 3 # same as inner[2] = 3
p outer, inner
我们将从分解这一点开始:
part_counts = Hash.new(Hash.new(0))
这等于说:
default_hash = { }
default_hash.default = 0
part_counts = { }
part_counts.default = default_hash
h = part_counts[pile_index]
h[part] += 1
稍后,你会这样说:
part_counts[pile_index][part] += 1
这等于说:
default_hash = { }
default_hash.default = 0
part_counts = { }
part_counts.default = default_hash
h = part_counts[pile_index]
h[part] += 1
您没有为哈希使用默认值的(正确)块形式,因此访问默认值不会自动激活密钥。这意味着part\u counts[pile\u index]
不会在part\u counts
中创建pile\u index
键,它只会为您提供part\u counts。默认值
,您实际上是在说:
h = part_counts.default
h[part] += 1
您没有执行任何其他操作来将键添加到part_counts
,因此它没有键,并且:
part_counts.keys == [ ]
那么为什么零件计数[0]
会给我们{:gear=>3,:spring=>2,:axe=>1}
<代码>零件计数
没有任何键,特别是没有0
键,因此:
part_counts[0]
与
part_counts.default
在上面访问part\u counts[pile\u index]
的地方,您实际上只是获得了对默认值的引用,哈希不会克隆它,您将获得下次哈希将使用的整个默认值。这意味着:
part_counts[pile_index][part] += 1
这是另一种说法:
part_counts.default[part] += 1
所以实际上您只是在更改part\u counts
的默认值。然后当你part\u计数[0]
时,你正在访问这个修改后的默认值,还有你意外地在循环中构建的{:gear=>3,:spring=>2,:axex=>1}