🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

2回答

852閲覧

配列[5, 2, 4, 6, 1, 3]を深いコピーをしたい

moon_light

総合スコア23

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2021/02/19 20:24

編集2021/02/20 18:25

やりたいこと・疑問点

挿入ソートを実装しています。
並べ替える過程を追いたくて、@resultに過程をpushしています。
同じ位置で

p ary
@result << ary

を書いているのに@resultには、ソート済みの配列が入っているのはなぜでしょうか?

該当のソースコード

ruby

1N=gets.to_i 2A=gets.split.map(&:to_i) 3 4@result = [] 5def insertionSort(tmp, n) 6 # ary=tmp.clone ←変更前 7 ary = Marshal.load(Marshal.dump(tmp)) 8 p [tmp.object_id, ary.object_id] 9 p [tmp[0].object_id, ary[0].object_id] 10 11 (1...n).each{|i| 12 p ary 13 @result << ary 14 15 v = ary[i] 16 j = i - 1 17 18 while j >= 0 && ary[j] > v do 19 ary[j+1] = ary[j] 20 j -= 1 21 end 22 ary[j+1] = v 23 } 24end 25 26insertionSort(A, N) 27p @result

入力

6
5 2 4 6 1 3

出力

[13220980, 13220860] # 異なる
[11, 11] # 同じ
[5, 2, 4, 6, 1, 3]
[2, 5, 4, 6, 1, 3]
[2, 4, 5, 6, 1, 3]
[2, 4, 5, 6, 1, 3]
[1, 2, 4, 5, 6, 3]
[[1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6]]

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gemmaro

2021/02/19 23:18

インスタンス変数 `@result` はどのような意図でしょうか.このコードはクラス定義の内部から抜粋したものですか?
moon_light

2021/02/20 18:25

すみませんm(__)m 修正しました。
guest

回答2

0

ソートが配列aryを直接書き換えることで行われているため、同じオブジェクトであるary@resultに入れても、そちらも変化し続けます。

投稿2021/02/19 23:54

maisumakun

総合スコア145963

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

moon_light

2021/02/20 18:32

回答ありがとうございます。 ↑のgemmaroさんへの回答を参考に、回答していただけるとありがたいです。m(__)m
guest

0

Rubyのドキュメントによると, ary = tmp.clone の箇所で使っている clone は, Array -> Object -> Kernel のように辿って, Kernel#clone [1] のことですね.これは

Produces a shallow copy of ...

とあるように,所謂深いコピーではないです.
ただ,この箇所が直接の問題ではなさそうで,注目すべきは result << ary のところです. result に何度か追加されたとしても, ary は shallow copy されたものなので,その正体はどれも同じですし, ary に対する最後の変更は result に含まれる他全ての要素に波及します.
質問文の出力で result の要素が 全て同じかつ整列された ary の可視化結果になっているのも頷けます.

参考

投稿2021/02/19 23:55

gemmaro

総合スコア358

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

moon_light

2021/02/20 18:30 編集

回答ありがとうございます。 回答していただいたことを調べたところ、参照・浅いコピー・深いコピーがあることを知りました。 そこで、深いコピーをすれば自分の望む出力が得られるのではないかと考え、 ary=tmp.clone ではなく ary = Marshal.load(Marshal.dump(tmp)) でコピーを行ってみたところ、出力の通りtmpとaryのobject_idは異なるのですが、 tmpとaryのそれぞれの要素のobject_idが同じになっていました。 これは、配列の要素が整数で、整数は Immutableだからということがわかりました。 ではtmpのような要素が整数(Immutable)の配列に対して、深いコピーを行うにはどのような方法を用いたら良いのでしょうか? 長いうえに分かりづらい文章で恐縮ですが回答いただけると幸いです。(__)
maisumakun

2021/02/20 23:40 編集

> tmpとaryのそれぞれの要素のobject_idが同じになっていました。 小さな整数については、同じ値のobject_idは必ず「同じ」です。整数オブジェクト自体はImmutableなので、これによる問題はありません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問