2012-07-17 74 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',它們將全部改變。