LoginSignup
1
1

More than 3 years have passed since last update.

【Ruby】二次元配列の宣言を間違えて、要素の変更が想定通りにできなかった原因と反省

Last updated at Posted at 2019-08-18

はじめに

Rubyをつかってコーディングテストに取り組んでいます。
その際に、いろいろなところを参考にして二次元配列を使ったときに、
値の書き換えがうまくいかずに失敗しました。

やりたかったこと

3x5の二次元配列を作成する。初期値はすべて0とする。
[0][0]の要素の値だけ、1に変更したい。

動作確認環境

  • Windows 10
  • ruby 2.5.5p157

失敗作

自分が最初に書いた失敗作のコードです。
line[0][0] だけ1に書き換えたかったのですが、line[1][0]line[2][0] も1に書き換わってしまいました。

line = Array.new(3, Array.new(5, '0'))

line.each do |n|
  p n
end
# 実行結果
# ["0", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]

line[0][0] = '1'
line.each do |n|
  p n
end
# 実行結果
# ["1", "0", "0", "0", "0"]
# ["1", "0", "0", "0", "0"]
# ["1", "0", "0", "0", "0"]

なぜ?

各行の配列が同じオブジェクトを参照していました。
下記の実行結果から、配列のオブジェクトIDが3つすべて「21014940」となっています。
そのため、line[0][0]だけ更新したつもりでも、結果的には同じオブジェクトを更新する結果になりました。

line = Array.new(3, Array.new(5, '0'))

line.each do |n|
  p n.object_id
end
# 実行結果
# 21014940
# 21014940
# 21014940

成功例1

最初の二次元配列を作る箇所をArray.new(3).map{Array.new(5, '0')} とすると、想定通りの結果を得ることができました。

line = Array.new(3).map{Array.new(5, '0')}

line.each do |n|
  p n
end
# 実行結果
# ["0", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]

line[0][0] = '1'
line.each do |n|
  p n
end
# 実行結果
# ["1", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]

もちろん配列のオブジェクトIDがそれぞれ異なるため、line[0][0]を更新した場合、他の配列に影響を与えることはありません。

line = Array.new(3).map{Array.new(5, '0')}

line.each do |n|
  p n.object_id
end
# 実行結果
# 21620400
# 21620240
# 21620080

成功例2

最初の二次元配列を作る箇所をArray.new(3) { Array.new(5,'0') } としてもよいです。
こちらのほうがコードが短いので、こちらのほうがよいかもしれません。

line = Array.new(3) { Array.new(5,'0') }
line.each do |n|
  p n
end

# 実行結果
# ["0", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]

line[0][0] = '1'
line.each do |n|
  p n
end
# 実行結果
# ["1", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]

おわりに

これのせいで、コーディングテストに失敗しました。
コーディングテストがおわったあと、参照が一緒なんだろうなぁとすぐ気づきました。
制限時間に追われて焦ってしまい、テスト中はさっぱり原因がわかりませんでした。

参考文献

Ruby 配列の初期化と多重配列 – こととこネット
【初心者必見】Ruby配列の初期化の方法まとめてみた!

1
1
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
1
1