質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.47%
Ruby

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

Q&A

解決済

2回答

1512閲覧

rubyのメソッドの基本的な仕様について。

fei2003

総合スコア9

Ruby

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

0グッド

0クリップ

投稿2015/02/28 07:51

現在入れた文字列の射影を取るメソッドを使っているのですが、その際に引数に指定した配列(ソースのa)がなぜだか変化してしまいます。
ソースを見ても原因がわからず、dupやcloneを使っても変化してしまうためお手上げ状態です。
ものすごく基本的な質問ですが、良ければ原因をお教え下さい。

lang

1def projection(db , series) 2 3 wo=0 4 5 while wo<db.length #dbの配列数 6 7 wi=0 8 while wi < series.length #系列の配列数だけ回す。 9 10 wa = 0 11 while wa < db[wo].length #db[wo]の配列数だけ回す。 12 13 14 if db[wo][wa].index(series[wi]) != nil #db配列要素の中に系列要素があった場合、if文の中に入る。 15 16 wu=0 #系列がある配列要素より前のdb配列要素をすべてカット 17 while wu < db[wo].length 18 db[wo][wu]=db[wo][wa+wu] 19 wu=wu+1 20 end 21 22 wu=0 #配列要素内の系列までの文字をすべてカット 23 we=db[wo][0].index(series[wi]) #dbの一つ目の系列がある場所 24 we = we+(series[wi].length-1) 25 while wu <= we 26 db[wo][0].slice!(0) 27 wu=wu+1 28 end 29 30 db[wo][0].insert(0,"_") #カットした場所に_を置く。 31 32 if db[wo][0]=="_\n" #カットしたことで配列の中身が_と改行のみになった場合、カットする。。 33 wu=0 34 while wu < db[wo].length 35 db[wo][wu]=db[wo][wu+1] 36 wu=wu+1 37 end 38 end 39 40 41 break 42 end 43 wa=wa+1 44 end 45 wi=wi+1 46 end 47 db[wo].compact! #空になった配列要素をカット 48 49 50 wo=wo+1 51 end 52 db.compact! #空になった配列要素をカット 53 return db 54end 55 56 57 58 59 60a=[["1234567890","123456789"],["1234567890","123456789"]] 61b=["3"] 62 63c=projection(a , b) 64 65p a 66

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

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

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

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

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

guest

回答2

0

2次元配列は、 dup や clone では、完全には 複製をつくることはできません。

次のプログラムを試してみてください。

lang

1# coding: utf-8 2 3def my_func(db) 4 db[0] = 'x' 5 db[0][0] = "y" 6 return db 7end 8 9def my_func_1(db) 10 work = db.clone 11 work[0] = "x" 12 work[1][0] = "y" 13 return work 14end 15 16def my_func_2(db) 17 work = Marshal.load(Marshal.dump(db)) 18 work[0] = "x" 19 work[1][0] = "y" 20 return work 21end 22 23a = [["1234567890","123456789"],["1234567890","123456789"]] 24c = my_func(a) 25puts "--- after my_func" 26p a 27p c 28 29a = [["1234567890","123456789"],["1234567890","123456789"]] 30c = my_func_1(a) 31puts "\n--- after my_func_1" 32p a 33p c 34 35a = [["1234567890","123456789"],["1234567890","123456789"]] 36c = my_func_2(a) 37puts "\n--- after my_func_2" 38p a 39p c

実行すると次のようになります。

$ ruby array.rb --- after my_func ["y", ["1234567890", "123456789"]] ["y", ["1234567890", "123456789"]] --- after my_func_1 [["1234567890", "123456789"], ["y", "123456789"]] ["x", ["y", "123456789"]] --- after my_func_2 [["1234567890", "123456789"], ["1234567890", "123456789"]] ["x", ["y", "123456789"]]

my_func, my_func_1, my_func_2 での配列の複写方法と、その複写した配列へに代入の結果の差がわかるとおもいます。
my_func_2 の方法で配列を複写すると、解決するとおもいます。

投稿2015/02/28 09:20

編集2015/03/02 14:45
katoy

総合スコア22324

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

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

fei2003

2015/03/01 16:19

ありがとうございます! こちらの方法も試してみます。
guest

0

ベストアンサー

projectionの中で、仮引数のdbが指すオブジェクトを書き換えているので、実引数のaにも影響が及びます。
Rubyの変数は、C等で言うとすべてポインタ(リファレンス)だと思ってください。

あと、オブジェクトを内部に含んだオブジェクト~~例えば["A","B"]~~の場合、clonedupをしても複製されるのは外側のオブジェクト(例だと[ ])だけで、内部に含まれたオブジェクト("A""B")は複製されず共有されます。

lang

1a=["A","B"] 2puts a.object_id #=>21104256 3puts a[0].object_id #=>21104280 4puts a[1].object_id #=>21104268 5 6b=a.clone 7puts b.object_id #=>21104160 aとは別オブジェクト 8puts b[0].object_id #=>21104280 a[0]と同一オブジェクト 9puts b[1].object_id #=>21104268 a[1]と同一オブジェクト

浅いコピー(shallow copy)と深いコピー(deep copy)に付いて調べてみてください。

db2 = db.cloneは浅いコピーなので、深いコピーならこの場合は、

lang

1db2 = db.map{|x| x.map{|y| y.clone}}

ですね。

投稿2015/02/28 08:16

編集2015/02/28 08:37
otn

総合スコア84618

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

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

fei2003

2015/02/28 08:36

ありがとうございます。 よく理解出来ました。
otn

2015/02/28 08:38

とりあえずの解決策を追記しておきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問