难题:
something = {}
another = something
('a'...'f').each do |x|
puts "another = #{another} and x= #{x} and something = #{something}"
another = (another[x] ||= {})
end
puts something
输出:
=>another = {} and x= a and something = {}
=>another = {} and x= b and something = {"a"=>{}}
=>another = {} and x= c and something = {"a"=>{"b"=>{}}}
=>another = {} and x= d and something = {"a"=>{"b"=>{"c"=>{}}}}
=>another = {} and x= e and something = {"a"=>{"b"=>{"c"=>{"d"=>{}}}}}
现在乍一看似乎是另一个'和'东西'两者都指向相同的哈希对象,但如果是这种情况,那么在输出中另一个哈希对象#39;会匹配某些东西'。那么变量'是什么'不是空哈希?
答案 0 :(得分:6)
在Ruby中,一切都是一个对象,所有对象都使用指针传递(有例外,但它们不适用于此处)。当你这样做
something = {}
another = something
创建单个Hash对象,并且两个变量都指向同一个对象。当你这样做
another[x] ||= {}
创建单个Hash对象,并将指向该对象的指针添加到 another
指向的哈希。另一种写作方式是
old_hash = another
new_hash = {}
old_hash[x] = new_hash
another = new_hash
请记住:所有这些分配只是围绕指向对象的指针移动。现在应该清楚another
指向新的(空)哈希。但是,由于old_hash
还包含指向新哈希的指针,因此another
将会看到新哈希值(即old_hash
)的任何期货更改。这就是为什么something
随着每次迭代而增长的原因。
你的例子与这种简单的情况没什么不同:
x = {}
y = {}
z = {}
x["a"] = y
y["b"] = z
z["c"] = {}
puts x
# {"a"=>{"b"=>{"c"=>{}}}}
您的示例只是反转最后三个分配 - 这对结果没有影响。
答案 1 :(得分:2)
现在乍一看它看起来像'另一个'和'某事'都指向同一个哈希对象,但如果是这样的情况那么 输出'另一个'将匹配'某事'。
因为something
和another
不再指向相同的对象。您已使用another
重新分配another = (another[x] ||= {})
。您可以致电something.object_id
和another.object_id
进行验证。
为什么
another
总是{}
因为你做的时候
another = (another[x] ||= {})
another
是通过评估表达式(another[x] ||= {})
返回的值{}
,这就是another
成为{}
的原因
并且,为了使您的代码正常工作,即您希望的方式只是删除another
的重新分配,以便another
和something
指向同一个对象。
something = {}
another = something
('a'...'f').each do |x|
puts "another = #{another} and x= #{x} and something = #{something}"
another[x] ||= {} ## Change to this
end
puts something
<强>输出:强>
another = {} and x= a and something = {}
another = {"a"=>{}} and x= b and something = {"a"=>{}}
another = {"a"=>{}, "b"=>{}} and x= c and something = {"a"=>{}, "b"=>{}}
another = {"a"=>{}, "b"=>{}, "c"=>{}} and x= d and something = {"a"=>{}, "b"=>{}, "c"=>{}}
another = {"a"=>{}, "b"=>{}, "c"=>{}, "d"=>{}} and x= e and something = {"a"=>{}, "b"=>{}, "c"=>{}, "d"=>{}}
=> "a"..."f"
2.1.0 :265 > puts something
{"a"=>{}, "b"=>{}, "c"=>{}, "d"=>{}, "e"=>{}}