Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby -> Writing to 2D Arrays

I am working on the array problems outlined in http://prepwork.appacademy.io/mini-curriculum/array/

I am trying to create the function, my_transpose, which takes in a matrix and returns its transpose.

I am very confused about writing to a 2D array! Here is a code - snippet that highlights my confusion.

rows = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8]
  ]

columns = Array.new(3 , Array.new(3))
puts columns.to_s #Output is a 3 x 3 array filled with nil
columns[0][0] = 0
puts columns.to_s #Output is [[0,nil,nil], [0,nil,nil], [0,nil,nil]]

Why does the modification to columns[0][0] change all three variables? Shouldn't it just change the first cell in the first row?

like image 210
bmillsiv Avatar asked Dec 25 '22 06:12

bmillsiv


2 Answers

columns = Array.new(3 , Array.new(3))

Here, Array.new(3) is called once, and the three sub-arrays of columns actually reference to this same Array object. Check out their object_id:

columns[0].object_id
# => 70296096047460
columns[1].object_id
# => 70296096047460
columns[2].object_id
# => 70296096047460

That's why modifying columns[0][0] makes columns[1][0] and columns[2][0] modified as well.


Use this instead:

columns = Array.new(3) {Array.new(3)}
like image 83
Yu Hao Avatar answered Jan 04 '23 23:01

Yu Hao


@YuHao has explained that you need:

Array.new(3) { Array.new(3) }

In fact, you can expand that slightly to create your transpose method:

def my_transpose(arr)
  Array.new(arr.size) { |i| Array.new(arr.size) { |j| arr[j][i] } }
end

my_transpose(rows)
  #=> [[0, 3, 6],
  #    [1, 4, 7],
  #    [2, 5, 8]] 

See Array::new.

like image 30
Cary Swoveland Avatar answered Jan 05 '23 00:01

Cary Swoveland