Array changing after concat function

Can someone shed some light on this problem. In the example, I am
attempting to concatenate two arrays together. However it appears that
the contents of the first array is being altered after using the concat
function even though a copy of the array is being used. Am I doing
something wrong here, or is this a potential bug?

Thanks

one = [[1],[2]]
two = [[‘a’],[‘b’]]

puts one.inspect

newArray =[]
count = 0

tempArr = Array.new(one)

tempArr.each do |x|
x = x.concat(two.values_at(count))
newArray = newArray.push(x)
count = count + 1
end

puts one.inspect

WKC CCC [email protected] wrote:

count = count + 1
end

puts one.inspect

Array.new(array) copies the array but it does not copy its elements.
So tempArr[0] is another name for the very same object as one[0], and so
forth. m.

I’ve found that using:

copy = one.map { |el| el.clone }

will copy all elements into the new array without referring to the same
object.
Is there a reason why the clone function has been ommitted from the API
doc?

unknown wrote:

WKC CCC [email protected] wrote:

count = count + 1
end

puts one.inspect

Array.new(array) copies the array but it does not copy its elements.
So tempArr[0] is another name for the very same object as one[0], and so
forth. m.

If they are referring to the same object, why is it when

tempArr = Array.new(one)
one.clear

results in tempArr still having the values originally assigned to array
one?

Thanks,

WKC CCC wrote:

I’ve found that using:

copy = one.map { |el| el.clone }

will copy all elements into the new array without referring to the same
object.
Is there a reason why the clone function has been ommitted from the API
doc?

But the “clone” method is included in the API documentation, it is a
question of locating which class it belongs to. Remember that members of
a
particular class inherit the methods of that class’s ancestors as well
as
its own.

For a given object, to display a sorted list of the methods available to
it,
do this:

puts (object).methods.sort.join("\n")

Hi –

On Fri, 8 Dec 2006, Paul L. wrote:

For a given object, to display a sorted list of the methods available to it,
do this:

puts (object).methods.sort.join("\n")

You don’t need to do the join("\n") – puts will puts each item in
turn.

David

Alle 18:37, giovedì 7 dicembre 2006, WKC CCC ha scritto:

If they are referring to the same object, why is it when

tempArr = Array.new(one)
one.clear

results in tempArr still having the values originally assigned to array
one?

Thanks,

tempArray and one are two different objects (as you can see using
object_id),
but the objects they contain are the same (again, use object_id to check
this: one[0].object_id and tempArray[0].object_id return the same
value).
When you call one.clear, you are changing the array itself, not the
objects
it contains. Instead, when in your block you call x.concat (where x is
one of
the elements of tempArray), you aren’t changing the tempArray, but its
elements.

The array and the objects it contains don’t speak to each other, so:

  • when you call an array’s method (array.clear, array.reverse!,…), you
    change the array. The objects it contains don’t change.
  • when you call an element’s method (such as, in your example, concat),
    you
    don’t change the array. Other variables referring to the same object,
    share
    that change.

I fear my explanation makes this topic look more confusing than it
actually
is, but I hope it’s useful.

Stefano

WKC CCC [email protected] wrote:

So tempArr[0] is another name for the very same object as one[0], and so
forth. m.

If they are referring to the same object, why is it when

tempArr = Array.new(one)
one.clear

results in tempArr still having the values originally assigned to array
one?

Reread what I said. I didn’t say that tempArr and one refer to the same
object; I said that tempArr[0] and one[0] (and so on) refer to the same
object.

Think of it this way. Items in an array are dogs. Arrays are people
holding leashes. Anyone can attach a leash to a dog. So I (tempArr) can
have a leash on Fido, and so can you (one). If you let go of your leash
(one.clear), Fido is still Fido; you just don’t have a leash on him. But
if you cut off one Fido’s legs (modify one[0]), that leg on my Fido
(tempArr[0]) is also cut off, because they are the same Fido.

m.

WKC CCC wrote:

I’ve found that using:

copy = one.map { |el| el.clone }

will copy all elements into the new array without referring to the same
object.
Is there a reason why the clone function has been ommitted from the API
doc?

It seems much simpler to just clone the array rather than each element
individually:

irb(main):001:0> a=[]
=> []
irb(main):002:0> 10.times{|i| a << i}
=> 10
irb(main):003:0> a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
irb(main):004:0> b = a.clone
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
irb(main):005:0> a[0] = 10
=> 10
irb(main):006:0> a
=> [10, 1, 2, 3, 4, 5, 6, 7, 8, 9]
irb(main):007:0> b
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

[email protected] wrote:

turn.
Thanks! I was in irb when I applied this non-“fix”.

Alle 21:49, giovedì 7 dicembre 2006, Drew O. ha scritto:

It seems much simpler to just clone the array rather than each element
irb(main):005:0> a[0] = 10
=> 10
irb(main):006:0> a
=> [10, 1, 2, 3, 4, 5, 6, 7, 8, 9]
irb(main):007:0> b
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Your code doesn’t solve the problem. If a contains mutable objects, such
as
arrays, what happens is this:

irb(main):001:0> a=[[1,2],[3,4]]
=> [[1, 2], [3, 4]]
irb(main):002:0> b=a.clone
=> [[1, 2], [3, 4]]
irb(main):003:0> b[0].push 5
=> [1, 2, 5]
irb(main):004:0> a
=> [[1, 2, 5], [3, 4]]
irb(main):005:0>

What clone (and dup) produce are shallow copies, that is the object is
copied,
but their contents are not: a contains exactly the same objects than b
does.
Because of this, you can’t change one of the elements of b whitout
changing
the element of a: the two are the same object.

Instead, what your example shows is that a and b are not the same
object: you
can add an element to a whithout changing b. But here you’re changing
the
arrays, not he objects they contain, which was the problem of the
original
poster.

Stefano

Thanks, this has helped.

Hi –

On Fri, 8 Dec 2006, Drew O. wrote:

It seems much simpler to just clone the array rather than each element
irb(main):005:0> a[0] = 10
=> 10
irb(main):006:0> a
=> [10, 1, 2, 3, 4, 5, 6, 7, 8, 9]
irb(main):007:0> b
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

But that won’t do a deep cloning, which is what it sounds like WKC
wants:

irb(main):001:0> a = [""]
=> [""]
irb(main):002:0> a[0].object_id
=> -604580558
irb(main):003:0> a.clone[0].object_id
=> -604580558
irb(main):004:0> a.map {|e| e.clone }[0].object_id
=> -604623258

David

Logan C. [email protected] wrote:

puts one.inspect
results in tempArr still having the values originally assigned to array
if you cut off one Fido’s legs (modify one[0]), that leg on my Fido
(tempArr[0]) is also cut off, because they are the same Fido.

m.

That is the most disturbed, and yet apt analogy ever

Clearly you’ve never read any of my books.

Mind if I quote you?

Woof! (That means “Be my guest.”) m.

unknown wrote:

Logan C. [email protected] wrote:

puts one.inspect
results in tempArr still having the values originally assigned to array
if you cut off one Fido’s legs (modify one[0]), that leg on my Fido
(tempArr[0]) is also cut off, because they are the same Fido.

m.

That is the most disturbed, and yet apt analogy ever

Clearly you’ve never read any of my books.

Mind if I quote you?

Woof! (That means “Be my guest.”) m.

(Off-topic to Matt)
The best languages are dead languages? Did I translate that correctly?

On Fri, Dec 08, 2006 at 05:35:09AM +0900, matt neuburg wrote:

one?
(tempArr[0]) is also cut off, because they are the same Fido.

m.

That is the most disturbed, and yet apt analogy ever. Mind if I quote
you?

Edwin F. [email protected] wrote:

That is the most disturbed, and yet apt analogy ever

Clearly you’ve never read any of my books.

Mind if I quote you?

Woof! (That means “Be my guest.”) m.

(Off-topic to Matt)
The best languages are dead languages? Did I translate that correctly?

Close enough. :slight_smile: m.