Is there a standard way of doing a deep copy of an object (in particular, of an array)? http://www.ruby-doc.org/core/classes/Object.html#M000379 mentions a function 'dclone', but this doesn't seem to exist: undefined method `dclone'
on 09.08.2007 10:14
on 09.08.2007 10:27
2007/8/9, Ronald Fischer <ronald.fischer@venyon.com>: > Is there a standard way of doing a deep copy of an object (in > particular, of an array)? copy_of_your_array = Marshal.load(Marshal.dump(your_array)) > http://www.ruby-doc.org/core/classes/Object.html#M000379 mentions a > function 'dclone', > but this doesn't seem to exist: > > undefined method `dclone' I've never seen that method. No idea. Kind regards robert
on 09.08.2007 15:32
On Aug 09, 2007, at 04:13 , Ronald Fischer wrote: > Is there a standard way of doing a deep copy of an object (in > particular, of an array)? > > http://www.ruby-doc.org/core/classes/Object.html#M000379 mentions a > function 'dclone', > but this doesn't seem to exist: > > undefined method `dclone' Ronald, I don't know about a "standard" way, however the method that I use to deep copy uses built in constructs: hashish = { :a => "a", :b => "b", :c => ["a","b","c"] } # some arbitrary object with references to other objects hashish_deep_copy = Marshal.load( Marshal.dump( hashish ) ) hashish_deep_copy will then be a deep copy of hashish. Hope this helps, ~Wayne s///g Wayne E. Seguin Sr. Systems Architect & Systems Administrator
on 09.08.2007 15:48
On Aug 09, 2007, at 09:30 , Wayne E. Seguin wrote: > <snip> > > hashish = { :a => "a", :b => "b", :c => ["a","b","c"] } # some > arbitrary object with references to other objects > > hashish_deep_copy = Marshal.load( Marshal.dump( hashish ) ) > > hashish_deep_copy will then be a deep copy of hashish. > > <snip> I have a library that I include in my projects which defines a deep_copy method on object: class Object def deep_copy( object ) Marshal.load( Marshal.dump( object ) ) end end Also please note that this method has some limitations due to limitations of Marshall. For example you won't be able to really dump IO, Proc, Singleton, Binding and a few other objects (Read the Marshal docs for more info). I hope this also helps, ~Wayne s///g Wayne E. Seguin Sr. Systems Architect & Systems Administrator
on 09.08.2007 16:12
On Thu, 09 Aug 2007 17:13:09 +0900, Ronald Fischer wrote: > Is there a standard way of doing a deep copy of an object (in > particular, of an array)? > > http://www.ruby-doc.org/core/classes/Object.html#M000379 mentions a > function 'dclone', > but this doesn't seem to exist: > > undefined method `dclone' Marshal.load(Marshsl.dump(array))
on 09.08.2007 16:14
On Thu, 09 Aug 2007 17:13:09 +0900, Ronald Fischer wrote: > Is there a standard way of doing a deep copy of an object (in > particular, of an array)? > > http://www.ruby-doc.org/core/classes/Object.html#M000379 mentions a > function 'dclone', > but this doesn't seem to exist: > > undefined method `dclone' It's annoying -- the ruby-doc core documentation includes all of the standard library, so it's hard to tell what comes from where. (Perhaps they can regenerate the documentation?) Anyway, if you click on the function name, you'll see the source code: # File lib/rexml/xpath_parser.rb, line 8 def dclone clone end
on 15.04.2010 18:36
> Marshal.load(Marshal.dump(array))
I'm curious, has anybody done any benchmarking of this method?
It seems to me this method would have the same kind of overhead &
performance hit as PHP's unserialize(serialize(object)).
I had a similar issue with deep copying an array just now...
Instead of using Marshal, I just extended Array with a roll-my-own:
class Array
def dclone
a = []
each { | x | a << x.dclone }
a
end
end
I think this is a much more robust solution, as it avoids added overhead
that may be hiding inside dump/load, and allows for the deep clone to
further use the children's deep clone methods.
I *believe* this is what the developers intended, as dclone begins as
simply an alias for clone (for basic objects, there's no need to go
deeper. Clone something with no children, and dclone *will* behave
exactly like clone).
This is of course only valid where dclone is defined (likely depends on
the version of ruby you're using). You can modify the above code to be
something more like this:
class Array
def dclone
a = []
each do | x |
if x.respond_to? :dclone
a << x.dclone
else
a << x.clone
end
end
end
end
I'm avoiding my usual habit of using the ? : trinary operator, for
clarity, here.