我正在进行ruby koans练习,并且对于test_default_value_is_the_same_object方法练习中的答案原因有点困惑。以下是代码:
def test_default_value_is_the_same_object
hash = Hash.new([])
hash[:one] << "uno"
hash[:two] << "dos"
assert_equal ["uno", "dos"], hash[:one]
assert_equal ["uno", "dos"], hash[:two]
assert_equal ["uno", "dos"], hash[:three]
end
我不确定为什么无论键是什么,值总是“uno”和“dos”?我认为当密钥为one
时,返回的值应为“uno”;当key为“two”时,返回的值应为“dos”。为什么不管键是什么,值总是一个数组?
谢谢,我期待着你的回答!
答案 0 :(得分:12)
hash = Hash.new([])
将使用[]
实例化一个新数组(让我们称之为Harvey),然后使用Harvey作为默认值进行哈希。
hash[:one]
不存在,所以你得到哈维。 Harvey使用"uno"
运算符(相当于Array#<<
)将harvey.push("one")
添加到他身上
hash[:two]
也不存在,所以你再次得到哈维(谁记得,已经包含"uno"
)。他现在也得到"dos"
。
hash[:three]
返回哈维,仍然使用他的"uno"
和"dos"
。
如果您希望代码的行为与您认为的那样,每个密钥中使用不同的数组,则每次需要默认时都需要返回一个新数组,而不是每次都使用Harvey:
hash = Hash.new { |h, k| h[k] = [] }
如果您只想让哈希与数组无关,请忽略Harvey,并使用Hash#[]=
代替Array#<<
:
hash = Hash.new()
hash[:one] = "uno"
hash[:two] = "dos"
答案 1 :(得分:0)
我也有同样的问题,但发现了这个答案,但并没有真正解释为什么这会使刚刚学习它的人感到困惑。仔细观察后,我发现了它为什么会如此运作。
def test_default_value_is_the_same_object
hash = Hash.new([])
hash[:one] << "uno"
hash[:two] << "dos"
assert_equal ["uno", "dos"], hash[:one]
assert_equal ["uno", "dos"], hash[:two]
assert_equal ["uno", "dos"], hash[:three]
assert_equal true, hash[:one].object_id == hash[:two].object_id
end
查看分配行:
hash[:one] << "uno"
hash[:two] << "dos"
每个赋值都是对不存在的键的引用,该键指向默认键,然后使用append操作符(<<)将元素添加到默认键的数组中。因此,对默认键数组的所有调用现在都是[“ uno”,“ dos”]。
这也是为什么断言将两个调用(hash [:one]和hash [:two])的ID均等地比较是正确的;它们都引用默认密钥。