2

I know this is probably not good Ruby style, but i'm learning... what's going on here? Specifically, why is the first row of my array a duplicate of the second row, when I think I'm initializing (copying) the values of the array parameter testa into @test, keeping all the indices the same?

class Test
    def initialize (size, testa)
        @test = Array.new(size, Array.new(size));
        (1..size).each { |r|
            (1..size).each { |c|
                @test[r-1][c-1] = testa[r-1][c-1];
                puts("#{r}, #{c}: #{@test[r-1][c-1]}");
            }
        }
    end
end

t= Test.new(2,[[1,2],[3,4]])    #=> @test=[[3, 4], [3, 4]]
Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
ppitha
  • 21
  • 1

2 Answers2

5

The cause of the problem you're seeing is how you're initializing the Array. You're passing along a single newly initialized array in the method call, which is used as the value for each row.

# Your initialization
@test = Array.new(size, Array.new(size));

# The following is equivalent, and perhaps more illustrative of what's happening
@a    = Array.new(size)
@test = Array.new(size, @a) # effective result => [@a, @a, @a, @a, @a] 

So in your method, as you iterate over the rows, you're repeatedly changing the values of the same array.

To fix it, create a new array for each row, rather than 1 array which is referenced 5 times. This can be accomplished using the block initialization variant of Array. Something like:

@test = Array.new(size) { Array.new(size) }

Check out the docs for more explanation on the different methods of Array initialization.

numbers1311407
  • 33,686
  • 9
  • 90
  • 92
1

See: http://www.ruby-doc.org/core/classes/Array.html to Array.new(size, obj)

is created with size copies of obj (that is, size references to the same obj)

The object 'Array.new(size)' it's the same object to each line.

Try: @test = Array.new(size) { Array.new(size) };

Or other implementation to your code:

class Test
  def initialize(array)
    @test = array.map{|ar| Array.new(ar) }
  end
end
t = Test.new([[1,2],[3,4]])
jlbfalcao
  • 111
  • 1
  • 2