ディープコピーオペレーターの作成に関するいくつかの異なる方法と投稿をいくつか検索しました。
Rubyでオブジェクトをディープコピーするための迅速で簡単な(組み込みの)方法はありますか?フィールドは配列またはハッシュではありません。
Ruby 1.9.2。
ディープコピーはVanilla Rubyに組み込まれていませんが、オブジェクトをマーシャリングおよびアンマーシャリングすることでハッキングできます。
Marshal.load(Marshal.dump(@object))
ただし、これは完全ではなく、すべてのオブジェクトで機能するわけではありません。より堅牢な方法:
class Object
def deep_clone
return @deep_cloning_obj if @deep_cloning
@deep_cloning_obj = clone
@deep_cloning_obj.instance_variables.each do |var|
val = @deep_cloning_obj.instance_variable_get(var)
begin
@deep_cloning = true
val = val.deep_clone
rescue TypeError
next
ensure
@deep_cloning = false
end
@deep_cloning_obj.instance_variable_set(var, val)
end
deep_cloning_obj = @deep_cloning_obj
@deep_cloning_obj = nil
deep_cloning_obj
end
end
ソース:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/Ruby/ruby-list/43424
Rubyオブジェクトのディープクローンを実行するためのネイティブ実装を作成しました。
マーシャルアプローチよりも約6〜7倍高速です。
https://github.com/balmma/Ruby-deepclone
このプロジェクトはもう保守されていないことに注意してください( 2017 での最後のコミット、報告されている issues )
Railsには、オブジェクトの詳細コピーを返すdeep_dup
という名前の再帰メソッドがあり、dup
およびclone
とは反対に、複合オブジェクト(配列/ハッシュ配列/ハッシュ)。次のように簡単です:
def deep_dup
map { |it| it.deep_dup }
end
Rubyオブジェクトのディープクローンを実行するネイティブ実装があります: Ruby_deep_clone
Gemでインストールします。
gem install Ruby_deep_clone
使用例:
require "deep_clone"
object = SomeComplexClass.new()
cloned_object = DeepClone.clone(object)
これは、マーシャルアプローチの約6〜7倍の速度で、凍結オブジェクトでイベントが機能します。
このプロジェクトはもう保守されていないことに注意してください( 2017 での最後のコミット、報告されている issues )
これには重複したgemを使用できます。
それは小さな純粋なRuby gemであり、オブジェクトを再帰的に複製することができます。新しい複製へのオブジェクト参照も複製します。
require 'duplicate'
duplicate('target object')
ネイティブのRuby=コアではなく、 ディープクローン メソッドではなく、多くの砂糖を追加するActiveSupport gemを使用することをお勧めします。
追加されたメソッドの詳細については、 documentation をご覧ください。
自動ディープクローンは常に必要なものではありません。多くの場合、選択したいくつかの属性を定義してディープクローンを作成する必要があります。これを行う柔軟な方法は、initialize_copy
、initialize_dup
、およびinitialize_clone
メソッドを実装することです。
クラスがある場合:
class Foo
attr_accessor :a, :b
end
:b
のみをディープクローンする場合は、initialize_*
メソッドをオーバーライドします。
class Foo
attr_accessor :a, :b
def initialize_dup(source)
@b = @b.dup
super
end
end
もちろん、@b
が独自の属性の一部をディープクローンしたい場合は、bのクラスで同じことを行います。
Railsはこれを行います( https://github.com/Rails/rails/blob/0951306ca5edbaec10edf3440d5ba11062a4f2e5/activemodel/lib/active_model/errors.rb#L78 を参照)
より完全な説明については、この投稿からここで学びました https://aaronlasseigne.com/2014/07/20/know-Ruby-clone-and-dup/
また、deep_diveも確認してください。これにより、オブジェクトグラフのディープコピーを制御できます。
あなたは本当にこれのために宝石を必要としません。これは、Gemのオーバーヘッドに見合うだけの価値はありませんが、これほど簡単なことはありません。
def deep_clone(obj)
obj.clone.tap do |new_obj|
new_obj.each do |key, val|
new_obj[key] = deep_clone(val) if val.is_a?(Hash)
end
end
end