On Wed, Aug 27, 2008 at 9:10 AM, Adam A. [email protected]
wrote:
How do i do that?
The problem with the above approach is that an array holds also
references
to the contained objects. So if you are changing what objects the array
contains
your approach is fine. If you are changing the contained objects
themselves, then
you have the same problem, since dup makes a shallow copy:
irb(main):001:0> a = %w{one two three}
=> [“one”, “two”, “three”]
irb(main):002:0> a.map {|x| x.object_id}
=> [-606229548, -606229578, -606229608]
irb(main):003:0> b = a.dup
=> [“one”, “two”, “three”]
irb(main):004:0> b[0] = “new value”
=> “new value”
irb(main):005:0> a
=> [“one”, “two”, “three”]
irb(main):006:0> b
=> [“new value”, “two”, “three”]
irb(main):007:0> b.map {|x| x.object_id}
=> [-606260528, -606229578, -606229608]
As you can see here, both a and b are referencing the same
string objects in their second and third position. So the strings
“two” and “three” are the same objects in both arrays. If you
change those objects the change will be reflected in both
arrays:
irb(main):008:0> a[2].upcase!
=> “THREE”
irb(main):009:0> a
=> [“one”, “two”, “THREE”]
irb(main):010:0> b
=> [“new value”, “two”, “THREE”]
If you want to avoid this, you need b to be a deep copy of a.
One way to achieve it is with Marshal:
irb(main):011:0> c = Marshal.load(Marshal.dump(a))
=> [“one”, “two”, “THREE”]
irb(main):012:0> c.map {|x| x.object_id}
=> [-606348068, -606348078, -606348088]
irb(main):014:0> a[2].downcase!
=> “three”
irb(main):015:0> a
=> [“one”, “two”, “three”]
irb(main):016:0> b
=> [“new value”, “two”, “three”]
irb(main):017:0> c
=> [“one”, “two”, “THREE”]
Although you should read a bit more on Marshal to understand if
it suits your needs.
Hope this helps,
Jesus.