2017-06-05 91 views
2

我想初始化三維紅寶石陣列。對於一個二維陣列,我可以做如何初始化三維紅寶石陣列

a = Array.new(4){ Array.new(5, 0) } 

所以我試圖

a = Array.new(4) { Array.new(5, Array.new(6, 0)) } 

但如果我不a[1][2][3] = 5,它不僅設置一個元件到5,其設置爲5相應的元素在其他子陣列中,即

[[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], 
[[0, 0, 0, 5, 0, 0], [0, 0, 0, 5, 0, 0], [0, 0, 0, 5, 0, 0], [0, 0, 0, 5, 0, 0], [0, 0, 0, 5, 0, 0]], 
[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], 
[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]] 

回答

4

問題是如果您將該值作爲參數傳遞,您將獲得一個數組,其中每個值都指向同一個對象。你做的正是與:

Array.new(5, Array.new(6, 0)) 

您可以使用Array#*,即數組乘法,而不是:

[[[0] * 6] * 5] * 4 
+0

這太好了,我必須接受它。 – Obromios

0

以下工作正常。

a=Array.new(4){ Array.new(5) { Array.new(6,0) }} 
1

只要使用相同的語法(與塊的,而不是一個參數:Array.new(n){...})爲所有的維度。

a = Array.new(4) { Array.new(5) { Array.new(6, 0) } } 

這樣,你的代碼將創建20個distincts的Array.new(6, 0)子子陣列,而不是複製同一個對象的5倍。

require 'pp' 
a = Array.new(4) { Array.new(5) { Array.new(6, 0) } } 
a[1][2][3] = 5 
pp a 
# [[[0, 0, 0, 0, 0, 0], 
# [0, 0, 0, 0, 0, 0], 
# [0, 0, 0, 0, 0, 0], 
# [0, 0, 0, 0, 0, 0], 
# [0, 0, 0, 0, 0, 0]], 
# [[0, 0, 0, 0, 0, 0], 
# [0, 0, 0, 0, 0, 0], 
# [0, 0, 0, 5, 0, 0], 
# [0, 0, 0, 0, 0, 0], 
# [0, 0, 0, 0, 0, 0]], 
# [[0, 0, 0, 0, 0, 0], 
# [0, 0, 0, 0, 0, 0], 
# [0, 0, 0, 0, 0, 0], 
# [0, 0, 0, 0, 0, 0], 
# [0, 0, 0, 0, 0, 0]], 
# [[0, 0, 0, 0, 0, 0], 
# [0, 0, 0, 0, 0, 0], 
# [0, 0, 0, 0, 0, 0], 
# [0, 0, 0, 0, 0, 0], 
# [0, 0, 0, 0, 0, 0]]] 
0

您可以使用遞歸來初始化任何維度的多維數組的元素。

代碼

def init(n, *rest) 
    rest.empty? ? Array.new(n, 0) : Array.new(n) { init(*rest) } 
end 

實例

dims = [2, 3, 2] 
a = init(*dims) 
    #=> [[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]] 

a[0][0][0] = 1 
a #=> [[[1, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]] 

dims = [2, 3, 2, 4, 2, 3] 
a = init(*dims) 

a.flatten.size 
    #=> 288 (= 2*3*2*4*2*3) 
a[0][0][0][0][0][0] = 1 
a.flatten.count(1) 
    #=> 1 

說明

的步驟如下。

假設,如在該示例中,

dims = [2, 3, 2] 

然後

n, *rest = dims 
    #=> [2, 3, 2] 
n #=> 2 
rest 
    #=> [3, 2] 

作爲rest.empty? #=> false,該方法返回

Array.new(2) { init(*[3, 2]) } # (1) 
    #=> [[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]] 

爲了獲得該結果,我們執行塊

{ init(*[3, 2]) } 

對於正在構建的陣列的兩個元素中的每一個。這需要我們計算init([3, 2])(與{ init(3, 2) }相同),這是按如下方式完成的。

n, *rest = [3, 2] 
    #=> [3, 2] 
n #=> 3 
rest 
    #=> [2] 

再次,如rest.empty? #=> false,我們上述(1)返回

Array.new(3) { init(*[2]) } # (2) 
    #=> [[0, 0], [0, 0], [0, 0]] 

到表達。對於每一個這種陣列的3種元素的我們執行塊

{ init(*[2]) } 

這就要求我們計算init([2]),這是如下完成的。

n, *rest = [2] 
    #=> [2] 
n #=> 2 
rest 
    #=> [] 

此時,由於rest.empty? #=> true,我們計算並返回

Array.new(2, 0) 
    #=> [0, 0] 

到表達式(2)的上方。

1是的,在Ruby中沒有這樣的「多維數組」,但我希望讀者知道我的意思。另一種類似於「......包含嵌套數組的嵌套數組,嵌套數組的嵌套級別」,但即使這樣也不完整,因爲它無法排除,例如[[1, [2,3]], [4,5]]。如果Ruby有這樣的對象的名字將會很有幫助。

+0

只有代碼才能回答在SO中被淹沒。請添加一些解釋! –