New to Ruby array acting weird

I have an array that’s acting weird, it starts as an empty array, I call
it “final_array”, and then I append a small array of only two members to
it, just called “array”, and that works fine. Then I swap the two
members of “array”, and they also swap inside “final_array”. It’s like
they’re linked together.

What am I doing wrong? Any help is greatly appreciated.

Here is my code…


array = [1,2]
final_array = []

append…

final_array << array

swap…

second_to_max_index = array.length - 2
max_index = array.length - 1
holder = array[second_to_max_index]
puts “----final array is #{final_array}”
array[second_to_max_index] = array[max_index]
puts “----final array is #{final_array}”
array[max_index] = holder
puts “----final array is #{final_array}”


Here is the output…

----final array is [[1, 2]]
----final array is [[2, 2]]
----final array is [[2, 1]]

I don’t understand what’s your expected output, But I answer you why it
changes final_array as well.

Actually

this line “final_array << array” pushes “array” as a first element of
“final array”, So Since you inserted this array into final array,
whatever
changes you make in array will be replicated in final array as well.

Please consider this point,

First element of array is “1”
First element of final_array is “[1,2]”

RAJ

Thank you, Raja. I expected that pushing an array onto an array would
really mean you I am pushing a copy, so that I could then modify the
original without affecting anything I might have copied it to. My code
example was more garbled than it had to be, sorry, I have a simpler
example below, and it demonstrates how what you say is only true some of
the time.

After appending array onto final_array, if I say “array[0] = 9999”, it
also changes final_array. However, if I then say “array = [7,7]”, no
change is made to final_array. I don’t understand why this is.

Thank you for your help. :slight_smile:

code…

array = [1,2]
final_array = []

puts "----final array is #{final_array} and array is #{array}"

final_array << array

puts "----final array is #{final_array} and array is #{array}"

array[0] = 9999

puts "----final array is #{final_array} and array is #{array}"

array = [7,7]

puts "----final array is #{final_array} and array is #{array}"

output…

----final array is [] and array is [1, 2]
----final array is [[1, 2]] and my_array is [1, 2]
----final array is [[9999, 2]] and my_array is [9999, 2]
----final array is [[9999, 2]] and my_array is [7, 7]

Ok ok, I got your problem,

Actually ruby variable datatype would be decided in the time of
assignment, not like C where you need to declare before you use.

So look at the example below , it might make understand clearly

a=34
puts a.class #Fixnum

a=‘something’
puts a.class #String

Now going further ,

a=[1,2,3]

a<<4

puts a #[1,2,3,4]

#So the above code insert 4 into array a

#But if you put using “=” operator, then variable would be changes to
the current value datatype like

a=4

puts a #4

Now here older array “[1,2,3,4]” was erased and 4 is replaced. Got me
what I am saying, Now let’s get into your problem,

array = [7,7] this line erases your older array, now array is the new
pointer, So array is changed but the final_array is not changed because
it still holds the older one.

Thank you, I have a better understanding of it now. I guess I’m always
going to have to be careful when pushing things onto an array.

So, I’ve tried to come up with the best way to do this, what I want is
to have the two-member array, push it onto final_array, and then swap
the two members of the original array, and push it again onto
final_array. Here’s what works, does it look reasonable to you?

Thank you.

array = [1,2]
final_array = [] # Ruby is not happy if I don’t declare this
temp_array = [] # Ruby is not happy if I don’t declare this

final_array << array

puts “#{final_array}” # [[1, 2]]

begin swap

temp_array << array[1]
temp_array << array[0]
array = temp_array

end swap

final_array << array

puts “#{final_array}” # [[1, 2], [2, 1]]

Hi Raja,

Thank you for explaining everything. I like your method better than
mine.

I never would have thought to try something like…

a[0],a[1]=a[1],a[0]

I think we have it solved now. I haven’t heard of the “clone” function
but I will look into it as well.

You’ve given me a much better understanding of things, it’s been a great
help. :slight_smile:

Thank you!!!

hi Jack Benson,

You are welcome.

Hi,

You are going in a long way, Swapping can be easily accomplished.

For an example,

a=1
b=2
b,a=a,b
puts a #2
puts b #1

In your case If “[[1, 2], [2, 1]]” is your output, Then

a=[1,2]
final_array=[]
final_array<<a
a[0],a[1]=a[1],a[0]
final_array<<a

puts final_array.inspect #[[2, 1], [2, 1]]

As show above you can have your output.

And I would like to point out another mistake of yours here,

YOU SAID:final_array = [] # Ruby is not happy if I don’t declare this

But declaration is only necessary when you want to push something,
declaration is not necessary if you want to assign an array
Example of this would be,

a=[1,2]

b=a # now b is regarded as array here you don’t need to declare “b”

c<<a # now c declaration is necessary because you are trying to insert
the value. The reason is, it will try to call a function like c.<<(a) So
it don’t know where to look for this function “<<”

you can use ‘clone’ function if you would like to create duplicate
array.

Perhaps this will help clarify what’s happening:

array = [1, 2]
final_array = []
final_array << array
puts “array id = #{array.object_id}”
puts “array[0] id = #{array[0].object_id}”
puts “f_a[0] id = #{final_array[0].object_id}”, ‘’

array[0] = 9999
puts “array id = #{array.object_id} after array[0] = 9999”
puts “array[0] id = #{array[0].object_id}”
puts “f_a[0] id = #{final_array[0].object_id}”, ‘’

array = [7, 7]
puts “array id = #{array.object_id} after array = [7, 7]”
puts “array[0] id = #{array[0].object_id}”
puts “f_a[0] id = #{final_array[0].object_id}”

Output (with annotations):

array id = 15296600
array[0] id = 3
f_a[0] id = 15296600 <-- same object as array, not a copy

array id = 15296600 after array[0] = 9999
array[0] id = 19999
f_a[0] id = 15296600 <-- array, final_array[0] still refer to same
object

array id = 15296240 after array = [7, 7] <-- a completely new array
array[0] id = 15
f_a[0] id = 15296600 <-- but this is still the old array

Your array ids will likely be different if you run it, but they should
match up (or differ, respectively) the same way.

array id = 15296600
array[0] id = 3
f_a[0] id = 15296600 <-- same object as array, not a copy

array id = 15296600 after array[0] = 9999
array[0] id = 19999
f_a[0] id = 15296600 <-- array, final_array[0] still refer to same
object

array id = 15296240 after array = [7, 7] <-- a completely new array
array[0] id = 15
f_a[0] id = 15296600 <-- but this is still the old array

Your array ids will likely be different if you run it, but they should
match up (or differ, respectively) the same way.

<<

Very Good explanation.

Brian,

Sorry for the late reply here. Thank you for the response. I didn’t know
about the object_id method, great tool. I just tried out your examples
line by line, great way to see what’s really going on. I feel much more
comfortable about it now that I always look at the object ids if things
get funny.

I appreciate the help. :slight_smile: Thank you!

You’re welcome – glad I could be of assistance!

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs