Copying an Array

Hi,

The = operator seems to retrieve an reference on a Array rather than
copying what it contains
as in the following code:

···

a = [1,2,3]
b = a

p b.id; p a.id
b.each_index do |i|
b[i] *= 2
end


both a and b equals to [2,4,6]

This can be solve by using a.collect or a.dup but the problem would
occur again if a,b are multi dimensions Array. dup or collect reference
on the sub-Array?
Isn’t there a clean and consise way to copy the whole content of an
multi dimension Array so that the copy is not somehow linked to the
original.

Btw, a would be modified even though it is accessed as attri_reader. So
I guess = is copying the pointer rather than any content (a.id == b.id)

(using ruby 1.6.8 (2002-12-24) [sparc-solaris2.8])

Thank you,
Fred

You want a deep copy of a nested array structure. As easy as that:

module Enumerable
def deep_copy
map {|x| x.respond_to?( :deep_copy ) ? x.deep_copy : x}
end
end

a=[[1,2],[3,4]]

b=a.dup
puts( a.equal?( b ) )
puts( a[0].equal?( b[0] ) )

b=a.deep_copy
puts( a.equal?( b ) )
puts( a[0].equal?( b[0] ) )

Yields:

false
true
false
false

Regards

robert

“Frederic Chalons - Design Support IA Student” frederic.chalons@st.com
schrieb im Newsbeitrag news:3ECB3715.7000204@st.com

Hi,

The = operator seems to retrieve an reference on a Array rather than
copying what it contains
as in the following code:


a = [1,2,3]
b = a

p b.id; p a.id
b.each_index do |i|
b[i] *= 2
end


both a and b equals to [2,4,6]

This can be solve by using a.collect or a.dup but the problem would
occur again if a,b are multi dimensions Array. dup or collect reference
on the sub-Array?
Isn’t there a clean and consise way to copy the whole content of an
multi dimension Array so that the copy is not somehow linked to the
original.

Btw, a would be modified even though it is accessed as attri_reader. So
I guess = is copying the pointer rather than any content (a.id ==
b.id)

···

(using ruby 1.6.8 (2002-12-24) [sparc-solaris2.8])

Thank you,
Fred

Hi,

The = operator seems to retrieve an reference on a Array rather than
copying what it contains
as in the following code:
*******
a = [1,2,3]
b = a

p b.id; p a.id
b.each_index do |i|
b[i] *= 2
end
********
both a and b equals to [2,4,6]

This can be solve by using a.collect or a.dup but the problem would
occur again if a,b are multi dimensions Array. dup or collect reference
on the sub-Array?
Isn't there a clean and consise way to copy the whole content of an
multi dimension Array so that the copy is not somehow linked to the
original.

Use Marshal:

def deep_clone(anObj)
  Marshal.load(Marshal.dump(anObj))
end

Btw, a would be modified even though it is accessed as attri_reader.

You can modify the arrays content, but you cannot assign a new object to
a (@a).

So I guess = is copying the pointer rather than any content (a.id == b.id)

= is just a reference assignment, does not copy anything except the
pointer at all.

Note that = or obj.a= are methods and not an assignment!
  
  a = [1,2,3]
  a[0] = 2 # This is no assignment! It's a method call!

Regards,

  Michael

···

On Wed, May 21, 2003 at 05:24:13PM +0900, Frederic Chalons - Design Support IA Student wrote:

Hi –

···

On Wed, 21 May 2003, Frederic Chalons - Design Support IA Student wrote:

The = operator seems to retrieve an reference on a Array rather than
copying what it contains

You can find coverage and discussion of Ruby variables at
http://www.rubycentral.com/book/tut_classes.html. In short, a
variable holds a reference to an object, so when you assign from one
variable to another, you’re copying that reference.

David


David Alan Black
home: dblack@superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Try this:

batsman@tux-chan:~/src/ctl$ ruby
module Enumerable
def deep_copy
map {|x| x.respond_to?( :deep_copy ) ? x.deep_copy : x}
end
end

a =
b = [a]
a << b
p a.deep_copy
^D

==> hangs

It’s safer to use Marshal…

···

On Wed, May 21, 2003 at 05:56:37PM +0900, Robert Klemme wrote:

You want a deep copy of a nested array structure. As easy as that:

module Enumerable
def deep_copy
map {|x| x.respond_to?( :deep_copy ) ? x.deep_copy : x}
end
end


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Save yourself from the ‘Gates’ of hell, use Linux." – like that one.
– The_Kind @ LinuxNet

Even more simply, { a = %w(hello world); b = a.deep_copy } hangs, since
String.each yields Strings.

martin

···

Mauricio Fern?ndez batsman.geo@yahoo.com wrote:

batsman@tux-chan:~/src/ctl$ ruby
module Enumerable
def deep_copy
map {|x| x.respond_to?( :deep_copy ) ? x.deep_copy : x}
end
end

a =
b = [a]
a << b
p a.deep_copy
^D

==> hangs