为什么Ruby Koans习题的about_hashes.rb中的test_default_value_is_the_same_object是数组的答案?

Why does the test_default_value_is_the_same_object in about_hashes.rb of Ruby Koans exercises have the answer of an array?

我正在做 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"?我想当key是one时,返回值应该是"uno";当key为"two"时,返回值应为"dos"。为什么无论键是什么,值总是一个数组?

谢谢,期待您的答复!

hash = Hash.new([])

将使用 [] 实例化一个新数组(我们称它为 Harvey),然后使用 Harvey 作为其默认值进行散列。

hash[:one]

不存在,所以你找到了哈维。 Harvey 使用 Array#<< 运算符(相当于 harvey.push("one")

添加到他身上 "uno"
hash[:two]

也不存在,所以你又得到了 Harvey(记住,他已经包含 "uno")。他现在也得到 "dos".

hash[:three]

returns Harvey,仍然带着他的 "uno""dos"

如果您希望代码表现得像您认为的那样,每个键中都有不同的数组,则每次需要默认值时都需要 return 一个新数组,而不是每次都使用 Harvey:

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

如果你只是想让散列与数组无关,请忽略 Harvey,并使用 Hash#[]= 而不是 Array#<<:

hash = Hash.new()

hash[:one] = "uno"
hash[:two] = "dos"

我遇到了同样的问题并找到了这个答案,但它并没有真正解释为什么这会让刚刚学习它的人感到困惑。仔细观察后,我发现了它的行为方式的原因。

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"

每个赋值都是对一个不存在的键的引用,该键指向默认键,然后使用追加运算符 (<<) 将一个元素添加到默认键的数组中。因此,对默认键数组的所有调用现在都是 ["uno"、"dos"].

这也是为什么将两个调用(hash[:one] 和 hash[:two])的 id 比较为相等的断言为真;他们都引用了默认密钥。