2012-07-17 93 views
1

考虑下面的Ruby代码:奇数红宝石行为

a = ["x"] * 3 # or a = Array.new(3, "x") 

a[0].insert(0, "a") 
a.each {|i| puts i} 

我希望可以将输出为斧,X,X(上当然是新的生产线)。但是,在Ruby 1.9.1中,输出是ax,ax,ax。这是怎么回事?我已经将问题缩小到定义数组a的方式。如果我明确写出

a = ["x", "x", "x"] 

然后代码按预期工作,但是原始代码中的任一版本都会给我这种意外的行为。看起来,* /初始化器意味着副本实际上是对字符串“x”的同一副本的引用。但是,如果不是我写的插入命令

a[0] = "a" + a[0] 

然后我得到所需的输出。这是一个错误,还是有一些我不了解的功能?

+0

相关但不完全相同:http://stackoverflow.com/questions/9835030/changing-one-array-in-an-array-of-arrays-changes-them-all-why?lq=1 – 2012-07-17 22:54:55

回答

7

的文档Array.new(size=0, obj=nil)

...它与大小的OBJ副本创建(即大小引用相同OBJ)。

Array * int

...返回通过连接的self

INT副本,这样在双方你惊讶的形式建立了一个新的数组,就像你想象的那样,最后你会得到三个同样的"x"对象的引用。我想说你可能会争论设计决定,但这是一个有记录的故意行为,而不是一个错误。

我知道得到你想要的行为,而无需手动编写数组文本(["x", "x", "x"])最好的办法是

a = Array.new(3) {"x"} 

或课程,只有三个元素,它没有太大的问题,但任何事情更大,这种形式派上用场。

+1

您可以在最后一个例子中,留下未使用的块变量。 – 2012-07-17 07:28:11

+0

@MichaelKohl谢谢 - 我不敢相信这些年来我一直都错过了这些细节! (现在更新了。) – 2012-07-17 07:55:45

+0

@DarshanComputing我甚至读过文档,还有一些错过了。谢谢!然而,这仍然让我想知道为什么'a [0] =“a”+ a [0]'只会在我的第一篇文章中初始化时修改第一个元素... – SL2 2012-07-17 17:03:20

0

总之,虽然“x”只是一个文字,但它是一个对象。您使用["x'] * 3,因此a包含3个相同的对象。您向其中一个插入'a',它们将全部改变。