Home > Mobile >  Why is multiple values of my 2-D Ruby array changing despite only changing one of it?
Why is multiple values of my 2-D Ruby array changing despite only changing one of it?

Time:11-08

I have the following code

visited = [[false]*4] * 3

which shows me the 2-D array

[[false, false, false, false], [false, false, false, false], [false, false, false, false]]

now I wish to change the element at row 1, column 2 as shown:

[[false, false, false, false], [false, false, false, false], [false, false, false, false]]
                                         ^

so I did the following:

visited[1][2] = 1

but now when I inspect the 2-D array, I get the following output:

puts visited.inspect
> [[false, false, 1, false], [false, false, 1, false], [false, false, 1, false]]

I can't seem to figure out why all the rows at the same column index get populated by 1?

Edit: I tried initializing my array visited by typing out all the elements manually (without multiplying the arrays) and it worked fine. I wonder why this is the case? Apologies if this is not the proper convention for doing so, I come from a Python background.

CodePudding user response:

You have three references to the same array. A change in one is a change in all three because there aren't really three at all.

This can be seen by using #object_id.

irb(main):005:0> visited = [[false]*4] * 3
=> [[false, false, false, false], [false, false, false, false], [false, false, false, false]]
irb(main):006:0> visited.map(&:object_id)
=> [70221746802920, 70221746802920, 70221746802920]

Now consider:

irb(main):008:0> visited = 3.times.map { [false] * 4 }
=> [[false, false, false, false], [false, false, false, false], [false, false, false, false]]
irb(main):009:0> visited.map(&:object_id)
=> [70221746635240, 70221746635200, 70221746635160]

All three arrays have unique object IDs.

irb(main):010:0> visited[0][2] = 42
=> 42
irb(main):011:0> visited
=> [[false, false, 42, false], [false, false, false, false], [false, false, false, false]]

CodePudding user response:

This is because in Ruby everything is an object, and Ruby defaults to passing a reference to that object. So your 2D array consists of three references to the same four member array. What you do to one, you do to all three.

  •  Tags:  
  • ruby
  • Related