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

时间:2015-02-20 19:43:43

标签: ruby immutability

这是我的代码:

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. 是否有一种方法可以使用许多相同的字符串填充数组来避免此问题?

2 个答案:

答案 0 :(得分:7)

这不是一个错误,只是行

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" }

答案 1 :(得分:1)

就像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"]