LoginSignup
0
0

More than 1 year has passed since last update.

【Ruby】二次元配列を複製する

Posted at

結論だけ知りたい方はコードへジャンプ

二次元配列を"複製"したのに、コピーを操作するとコピー元も変わってしまう…

AtCoder Beginner Contestにてそんな事象にぶつかってしまい、時間内に解決できませんでした。

たとえば

arr = [[1,2,3],[4,5,6],[7,8,9]]

このような二次元配列を想定します。
これをdupで複製し、項を操作すると…

copy = arr.dup
copy[0][0] = 100

p arr
# => [[100,2,3],[4,5,6],[7,8,9]]
# copyはarrとは別のオブジェクトなのに、copyを操作するとarrも変わってしまった。

複製したのになぜコピー元が影響を受けてしまうんだろう?と頭を捻りました。

なぜコピー元が影響を受けてしまうのか?

copyは確かにarrを複製した別のオブジェクトですが、copy[0]が持っているのはプリミティブな値ではなく、[1,2,3]を格納している参照値(ざっくり言うとメモリアドレスx)を持っています。
つまり、arrでもcopyでも、同一のメモリアドレスxを参照しているのです。
したがってcopyはarrとは別のオブジェクトですが、その中身の配列については、同一の参照先を見るので、同一のオブジェクトです。

arr = [メモリアドレスxの参照値, メモリアドレスyの参照値, メモリアドレスzの参照値]
copy = arr.dup
# copyとarrは間違いなく別のオブジェクトだが…
# copy = [メモリアドレスxの参照値, メモリアドレスyの参照値, メモリアドレスzの参照値]である。
# arrもcopyも同じ参照先を見るので、arr[0]とcopy[0]が指すオブジェクトは同一オブジェクト
# 従って、copy[0][0]を操作すれば、arr[0][0]も影響を受けてしまう。

二次元配列の複製方法

二次元目の配列も複製するためには、一次元目の配列で新しいオブジェクトを用意し、二次元目の配列もdupなどで複製してやる必要があります。

arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
copy = []
arr.each do |arr2|
  copy.push(arr2.dup)
end

copy[0][0] = 100
p arr
# => [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# copyの要素を変更したが、arrは影響を受けていない。

以上となります。
もしもっと楽に二次元配列を複製する方法がありましたら、ぜひご教授ください。
ご覧いただきありがとうございました!

0
0
1

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