2017-11-07 35 views
0

にこのコードを変更しません:それは回転しなかった理由Rubyのブロックは、ここでは、ローカル変数

def create_sym_matrix 
    ran_arr = Array.new(5){rand(1..100)} 
    ran_arr[1] = 0 
    mat_arr = Array.new(5){|i|ran_arr.push(ran_arr.shift)} 
    Matrix.columns(mat_arr) 
end 

aa = create_sym_matrix 

=> Matrix[[86, 86, 86, 86, 86], [0, 0, 0, 0, 0], [20, 20, 20, 20, 20], 
[39, 39, 39, 39, 39], [48, 48, 48, 48, 48]] 

誰かが私に説明できますか?私は対角線上にゼロを持つ対称マトリックスを得ようとしていました。

答えて

2

Array::newのドキュメントは説明しています

新しい(サイズ= 0、デフォルト= nilの)
新しい(配列)
新しい(サイズ){|インデックス|ブロック}
...

最後の形式では、指定されたサイズの配列が作成されます。この配列の各要素は、要素のインデックスを指定されたブロックに渡して戻り値を格納することによって作成されます。

ブロック{|i|ran_arr.push(ran_arr.shift)}は、常に同じ値を返します。ran_arrに格納された配列。新しい配列には、ran_arrへの5つの参照が含まれています。 mat_arrの行には、5つの異なる行がないため、同じ値が含まれています。それは5回リンクされた同じオブジェクトです。

mat_arr = Array.new(5){|i|ran_arr.push(ran_arr.shift).clone} 

あなたはそれがまだ対角線上のゼロで行列を生成しないことがわかります:あなたはブロックからran_arrのコピーを返す必要があり、この問題を解決するには

。この目標を達成するには、アルゴリズムを修正する必要があります。

def create_sym_matrix 
    ran_arr = Array.new(5){rand(1..100)} 
    ran_arr[4] = 0 
    mat_arr = Array.new(5){|i|ran_arr.unshift(ran_arr.pop).clone} 
    Matrix.columns(mat_arr) 
end 

出力を:

Matrix[[0, 38, 8, 48, 73], [73, 0, 38, 8, 48], [48, 73, 0, 38, 8], [8, 48, 73, 0, 38], [38, 8, 48, 73, 0]] 
+0

はどうもありがとうございました!ブロックが同じ値を繰り返し返す理由を説明できますか? – gavvel

+1

Rubyオブジェクトは参照によってコピーされます。これは、 'a = ran_arr'は' ran_arr'の値を複製しないことを意味し、新しい名前を作成するだけです。 – axiac

+1

ブロックは実行するたびに 'ran_arr'を変更します。 5回の回転の後、 'ran_arr'の値は' ran_arr'が作成された時と同じ順序で残されます。 – axiac

関連する問題