初始化具有相同元素的数组:`==` 运算符表示数组相同,但它们的行为不同。为什么?

Initializing an array with identical elements: `==` operator says arrays are the same, but they behave differently. Why?

这是我的代码:

a=["foo","foo","foo"]
b=["foo"]*3
a==b # => true

a.each{|i| i<<"bar"}
b.each{|i| i<<"bar"}
a==b # => false

我得到了我对 a 的期望:

["foobar", "foobar", "foobar"]

但是对于 b,我得到这个:

["foobarbarbar", "foobarbarbar", "foobarbarbar"]
  1. 为什么会这样?这是一个错误吗?
  2. 有没有办法用许多相同的字符串填充数组来避免这个问题?

这不是错误,只是行

a=["foo","foo","foo"]
b=["foo"]*3

不一样。第二个是将 SAME OBJECT 插入 b 数组三次。在 a 数组中,您有三个不同的对象。在所有情况下,对象都是带有文本 "foo".

的字符串

您可以通过检查对象 ID 来确认这一点。

a[0].object_id == a[1].object_id
=> false

b[0].object_id == b[1].object_id
=> true

所以当你用 << "bar" 改变对象时,你正在改变同一个对象三次(在数组 b 的情况下)

要用同一字符串的不同实例填充数组,请执行...

Array.new(3) { "foo" }

正如 SteveTurczyn 所说,["foo"]*3 创建一个数组,将同一对象的副本连接三次 ("foo")。

如果你想应用一些函数或对数组的元素做些什么。使用方法map!

喜欢:

a = ["foo", "foo", "foo"]
 => ["foo", "foo", "foo"]
a.map! { |x| x + "bar" }
 => ["foobar", "foobar", "foobar"]

b = ["foo"]*3
 => ["foo", "foo", "foo"]
b.map! { |x| x + "bar" }
 => ["foobar", "foobar", "foobar"]