LoginSignup
2
0

【Ruby】Array.newによる配列の生成

Posted at

はじめに

プログラミング問題で遊んでいた時のことです。

2次元配列を生成して、条件を満たしている要素を書き換えていこうとしたところ、

「ん?思ったのと違う要素まで書き換えられてるやん。あ〜、他の行と同じ配列を参照してるからか。」

と気がつくことはできたものの、いざ、それぞれの行で独立した配列を生成しようとすると手が止まる…

その時は力技で凌ぎましたが、もう少し綺麗に書きたいなと思い、調べた時のことをまとめておきます。

結論

縦2 × 横3の配列であれば、次のように生成します。

array = Array.new(2){ Array.new(3) }

各行が独立していない配列の生成

はじめに試して、うまくいかなかった配列の生成方法です。

newメソッドの第1引数で1次元目(縦)の要素数を、第2引数で2次元目(横)に入る配列(=生成した配列)を指定しています。

array1 = Array.new(2, Array.new(3))
p array1 # => [[nil, nil, nil], [nil, nil, nil]]

array1[0][1] = 1
p array1 # => [[nil, 1, nil], [nil, 1, nil]]

上記のとおり、array1[0][1]を書き換えたいだけなのに、array1[1][1]が一緒に書き換えられてしまっています。

1行目と2行目が同じ配列を参照しているということをobject_idで確認してみます。

p array1[0].object_id # => 60
p array1[1].object_id # => 60

Array.new(3)は1度だけ実行されて、その評価結果(=同じオブジェクト)が各行に入るので、このような結果となります。

各行が独立している配列の生成方法(力技)

実際に問題を解いている時は時間的なこともあり、いい方法をすぐに見つけられなかったので、すぐに思いついた次の方法で配列を生成しました。

array2 = []
2.times{ array2 << []}
array2.each do |val|
  3.times{ val << nil }
end

空の配列を作成→さらにその中に空の配列を作成→要素を1つずつ入れていくという流れです。

結果は意図どおりになっていますが、今あらためて見てもイケてない…

というわけで、もう少し綺麗に書きたいという今回の記事に繋がりました。

p array2 # => [[nil, nil, nil], [nil, nil, nil]]

array2[0][1] = 1
p array2 # => [[nil, 1, nil], [nil, nil, nil]]

p array2[0].object_id # => 60
p array2[1].object_id # => 80

各行が独立している配列の生成方法

冒頭の結論に書いているとおり、こちらの方法で生成します。

array3 = Array.new(2){ Array.new(3) }

最初の方法との違いは、2次元目の配列を第2引数ではなく、ブロックで渡していることです。

ブロックは要素ごとに実行され、その評価結果が各行に入る、つまり各行には違うオブジェクトが入るということになります。

(公式リファレンスのここに書かれているので、あわせてご参照ください。)

確認すると、次のとおり意図した結果が出力されます。

p array3 # => [[nil, nil, nil], [nil, nil, nil]]

array3[0][1] = 1
p array3 # => [[nil, 1, nil], [nil, nil, nil]]

p array3[0].object_id # => 60
p array3[1].object_id # => 80

さいごに

私の結論としては「2次元目の配列をブロックで渡す」ということになりました。

「もっといい方法知ってるよ!」「こんな方法もあるよ!」という方がいらっしゃいましたら、ぜひ教えてください!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0