2017-06-05 19 views
2

3次元ルビ配列を初期化したい。二次元アレイのために、私は3次元ルビ配列を初期化する方法

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

この方法で、あなたのコードではなく、同じオブジェクトを5回複製の20 distincts Array.new(6, 0)サブサブ配列を作成します。

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 

説明

手順です。

rest.empty? #=> falseように、方法は

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

この結果を得るに戻るそして

dims = [2, 3, 2] 

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

、例のように、と仮定は、我々は、ブロックを実行

{ init(*[3, 2]) } 

である。これには、init([3, 2]){ init(3, 2) }と同じ)を計算する必要があります。これは次のように行われます。

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

再び、rest.empty? #=> falseとして、我々は、式に

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

を返す(1)上記。この配列の3つの要素のそれぞれについて、我々はブロック

{ init(*[2]) } 

を実行これは、次のように行われている、init([2])を計算するために私たちを必要とします。

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

今回は、rest.empty? #=> true以来、我々は計算し、(2)上記の式に

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

を返します。

1はい、Rubyには「多次元配列」はありませんが、私は読者に何を意味するのかを知ってもらうことを期待しています。代替は、「同じサイズのネストされた配列を含む配列の任意の数のネストレベル」ですが、除外に失敗しても完全ではありません。たとえば、[[1, [2,3]], [4,5]]です。 Rubyがそのようなオブジェクトの名前を持っていれば役に立ちます。

+0

コードのみの回答は、SOに尋ねられます。いくつかの説明を追加してください! –

関連する問題