1

元の配列を変更せずに、配列のコピーを変更しようとしています。これはハッシュの配列なので、使用する配列の「まったく新しい」コピーを作成するには:

foo = [ { :a => "aaaaaa" } ]
foocopy = foo.map { |h| h.dup }

コピーのハッシュの文字列にデータを追加したい。

とを使用する=と正常に動作します+

foocopy.first[:a] = foocopy.first[:a] + "bbbbb"
foo
=> [{:a=>"aaaaaa"}]  # original unchanged as expected
foocopy
=> [{:a=>"aaaaaabbbbb"}]

ただし、それを使用する<<と、コピーとオリジナルの両方が変更されます。

foocopy.first[:a] << "cccccc"
foo
=> [{:a=>"aaaaaacccccc"}]   # ORIGINAL got changed too
foocopy
=> [{:a=>"aaaaaacccccc"}]

それはRubyのバグですか?

4

2 に答える 2

2

dupオブジェクトの「浅いコピー」を実行します。つまり、同じキーと値を持つ新しいハッシュを作成しています! 残念ながら、Ruby にはハッシュの「ディープ コピー」を作成するための優れた組み込み方法がありません。この場合、参照されるすべてのオブジェクトもコピーされます。それで、あなたは何をすべきですか?

を使用する最適な解決策を既に見つけたと思います+=。これ+は、新しいオブジェクトを作成し=、コピーされたオブジェクトを上書きするためです。

しかし、Ruby でオブジェクトをディープ コピーするための簡単なハックがあります。これは、 Marshalを使用してオブジェクトをシリアル化/非シリアル化することです。

foo = [ { :a => "aaaaaa" } ]
foocopy = Marshal.load(Marshal.dump(foo))

そうすれば、ポインターがオブジェクト間で共有されるため、驚くことはありません。そして、<<コードは期待どおりに機能します。

于 2015-07-02T19:35:56.790 に答える
2

いいえ、これは配列とハッシュを複製したためですが、文字列は同じ id を持つオブジェクトであり、ruby は文字列を奇妙な方法で処理します。

irb(main):001:0> foo = [ { :a => "aaaaaa" } ]
=> [{:a=>"aaaaaa"}]
irb(main):002:0> foocopy = foo.map { |h| h.dup }
=> [{:a=>"aaaaaa"}]
irb(main):003:0> foo.object_id
=> 70252221980900
irb(main):004:0> foocopy.object_id
=> 70252221915920
irb(main):005:0> foocopy.first.object_id
=> 70252221915880
irb(main):006:0> foo.first.object_id
=> 70252221980940
irb(main):007:0> foocopy.first[:a].object_id
=> 70252221980960
irb(main):008:0> foo.first[:a].object_id
=> 70252221980960

これは、a+bこのオブジェクトを変更されたものに再インスタンス化し、a << bオブジェクトのインスタンスを変更することを意味します。これが実際のメソッドの動作です。

文字列だけで:

irb(main):009:0> a = "test"
=> "test"
irb(main):010:0> b = a.dup
=> "test"
irb(main):011:0> a.object_id
=> 70252221685660
irb(main):012:0> b.object_id
=> 70252221662100
irb(main):013:0> a = a + "1"
=> "test1"
irb(main):014:0> a.object_id
=> 70252221586140
irb(main):015:0> b << "1"
=> "test1"
irb(main):016:0> b.object_id
=> 70252221662100

そしてドキュメントから:

http://ruby-doc.org/core-2.2.0/String.html#method-i-2B

http://ruby-doc.org/core-2.2.0/String.html#method-i-3C-3C

于 2015-07-02T19:15:46.290 に答える