我做了一些搜索,发现了一些关于创建深拷贝操作符的不同方法和帖子。
是否有一种快速简便的(内置)方式在Ruby中深度复制对象?字段不是数组或散列。
使用Ruby 1.9.2。
答案 0 :(得分:62)
深层拷贝并不构建在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
答案 1 :(得分:16)
答案 2 :(得分:7)
Rails有一个名为deep_dup
的递归方法,它将返回一个对象的深层副本,与dup
和clone
相反,它甚至可以在复合对象上工作(数组/哈希)数组/哈希)。
它很简单:
def deep_dup
map { |it| it.deep_dup }
end
答案 3 :(得分:6)
有一个本机实现来执行ruby对象的深层克隆:ruby_deep_clone
使用gem安装它:
gem install ruby_deep_clone
使用示例:
require "deep_clone"
object = SomeComplexClass.new()
cloned_object = DeepClone.clone(object)
它比Marshal方法快6到7倍,事件与冻结物体一起使用。
答案 4 :(得分:3)
你可以使用重复的宝石。
这是一个小的纯红宝石宝石,能够递归复制对象 它也会将它的对象引用复制到新的复制中。
require 'duplicate'
duplicate('target object')
答案 5 :(得分:2)
我建议您使用ActiveSupport gem,它会为您的原生Ruby核心添加大量糖,而不仅仅是deep clone方法。
您可以查看documentation以获取有关已添加方法的更多信息。
答案 6 :(得分:2)
自动深度克隆并不总是您想要的。通常,您需要定义选定的几个属性以进行深度克隆。一种灵活的方法是实施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的课程中也会这样做。
有关更完整的解释,我在此帖https://aaronlasseigne.com/2014/07/20/know-ruby-clone-and-dup/
中了解到了这一点答案 7 :(得分:1)
同时查看deep_dive。这允许您对对象图进行受控深度复制。
答案 8 :(得分:0)
您真的不需要宝石。这比这简单得多,这不值得拥有宝石的开销!
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