如何在Ruby中创建对象的深层副本?

B S*_*ven 50 ruby copy ruby-on-rails object deep-copy

我做了一些搜索,发现了一些关于创建深度复制操作符的不同方法和帖子.

是否有一种快速简便的(内置)方式来深入复制Ruby中的对象?字段不是数组或散列.

在Ruby 1.9.2中工作.

Ale*_*tie 65

深层副本不是内置于vanilla Ruby中,但您可以通过编组和解组对象来破解它:

Marshal.load(Marshal.dump(@object))
Run Code Online (Sandbox Code Playgroud)

但这并不完美,并不适用于所有对象.一种更健壮的方法:

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
Run Code Online (Sandbox Code Playgroud)

资源:

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/43424

  • 显然,它还假设对象首先是可编组的,而不是所有对象都是. (4认同)
  • 是的,相对而言,它只是慢了 - 如果一次克隆大量对象,您只会注意到 (2认同)

小智 16

我已经创建了一个本机实现来执行ruby对象的深层克隆.

它比Marshal方法快约6至7倍.

https://github.com/balmma/ruby-deepclone

  • 据作者说,这个项目不再维护,也没有准备好生产. (7认同)

Cla*_*ani 8

导轨具有名为递归方法deep_dup,将返回的对象的深拷贝,并且,在相反的dupclone,作品即使在复合对象(列/散列的阵列/散列).它很简单:

def deep_dup
  map { |it| it.deep_dup }
end
Run Code Online (Sandbox Code Playgroud)

  • Rails 的 Object#deep_dup 实际上是浅层“dup”调用。除了哈希和数组之外,您需要实现自己的“deep_dup”才能正常工作。 (2认同)

小智 6

有一个本机实现来执行ruby对象的深层克隆:ruby_deep_clone

用gem安装:

gem install ruby_deep_clone
Run Code Online (Sandbox Code Playgroud)

用法示例:

require "deep_clone"
object = SomeComplexClass.new()
cloned_object = DeepClone.clone(object)
Run Code Online (Sandbox Code Playgroud)

它比Marshal方法快6到7倍,事件与冻结物体一起使用.

  • 据作者说,这个项目不再维护,也没有准备好生产. (4认同)
  • 不幸的是,这个gem不处理从Array继承并包含它们自己的复杂嵌套类的自定义Collection类.Ruby_deep_clone将这些对象转换为数组,并且它们会丢失自定义属性. (2认同)