Suppose a code is like this:
array1 = [1,2,3,4,5]
array2 = array1
array2.delete(1)
And the result was:
array2 => [2,3,4,5]
array1 => [2,3,4,5]
How do I make sure the first array stays original after the modification
of second array?
Suppose a code is like this:
array1 = [1,2,3,4,5]
array2 = array1
array2.delete(1)
And the result was:
array2 => [2,3,4,5]
array1 => [2,3,4,5]
How do I make sure the first array stays original after the modification
of second array?
Hi Vincent,
Try array1.dup, eg:
array2 = array1.dup
Cheers,
Garth
Vincent S. wrote in post #1105954:
How do I make sure the first array stays original after the modification
of second array?
Variables in ruby hold references to objects. This can be evidenced by
viewing the object_ids:
irb:001> array1 = [1,2,3,4,5]
irb:002> array2 = array1
irb:003> array2.object_id
=> 70171269757120
irb:004> array1.object_id
=> 70171269757120
To de-duplicate the reference you need to create a second object, which
is a copy of the first. The simplest way is to use dup
irb:005> array2 = array1.dup
irb:006> array1.object_id
=> 70171269757120
irb:007> array2.object_id
=> 70171269775520
irb:008> array1.delete(1)
irb:009> array1
=> [2, 3, 4, 5]
irb:010> array2
=> [1, 2, 3, 4, 5]
The thing to remember is that Array#dup performs a shallow copy. For
example:
irb:011> array1 = [[1,2,3],[4,5]]
irb:012> array2 = array1.dup
irb:013> array1[0].delete(1)
irb:014> array1
=> [[2, 3], [4, 5]]
irb:015> array2
=> [[2, 3], [4, 5]]
The variables array1
and array2
point to different Array objects,
but each of those independently maintains references to the same
inner-arrays. In other words, array1[0] and array2[0] both reference
the same object.
It’s not only limited to arrays, either:
irb:016> array1 = [‘a’]
irb:017> array2 = array1.dup
irb:018> array1[0] << ‘b’
irb:019> array1
=> [“ab”]
irb:020> array2
=> [“ab”]
There is no general-form solution to creating a deep-copy of a
datastructure in ruby.
On Tue, Apr 16, 2013 at 9:10 PM, Matthew K.
[email protected]wrote:
There is no general-form solution to creating a deep-copy of a
datastructure in ruby.
A (suboptimal) solution for deep copies in Ruby is to use Marshal.
It sure would be nice if Ruby had some sort of analogue for structured
cloning.
Thanks much for help!
On Wed, Apr 17, 2013 at 7:34 AM, Tony A.
[email protected]wrote:
What exactly do you mean by “structured cloning”? Do you have ideas how
that should work?
Sketch:
class CloneContext
def initialize
@store = {}
end
def deep_clone(*objs)
objs.map do |o|
copy_one(o) rescue o
end
end
private
def copy_one(obj)
@store.fetch obj.object_id do |oid|
(@store[oid] = obj.class.allocate).tap do |copy|
# add specific handling for Array, String etc. or delegate to
#clone method of obj
obj.instance_variables.each do |var|
copy.instance_variable_set(deep_clone(obj.instance_variable_get(var)))
end
end
end
end
end
Kind regards
robert
On Wed, Apr 17, 2013 at 5:51 AM, Vincent S.
[email protected]wrote:
How do I make sure the first array stays original after the modification
of second array?
Adding to what Garthy said: you need to be aware that there is only one
Array, not two as your speaking of a “first array” and “second array”
indicates. The effect is called “aliasing”: two variables reference the
same instance. Btw, it happens all the time, for example when invoking
methods.
Another way of preventing changes to an Array is freezing it. That does
not automatically freeze the contained objects though!
Yet another way is to do the filtering in one step
irb(main):001:0> array1 = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
irb(main):002:0> array2 = array1.reject {|x| x == 1}
=> [2, 3, 4, 5]
irb(main):003:0> array2 = array1[1…-1]
=> [2, 3, 4, 5]
irb(main):004:0> array2 = array1.slice(1…-1)
=> [2, 3, 4, 5]
irb(main):005:0> array1
=> [1, 2, 3, 4, 5]
Kind regards
robert
On Wed, Apr 17, 2013 at 3:00 AM, Robert K.
[email protected]wrote:
What exactly do you mean by “structured cloning”? Do you have ideas how
that should work?
You can think of it as being somewhat akin to the marshal/unmarshal
approach, minus the intermediate string representation. For more
information I’d suggest reading how ECMAScript does it:
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.
Sponsor our Newsletter | Privacy Policy | Terms of Service | Remote Ruby Jobs