Ruby: неожиданные результаты для инициализации многомерного массива - PullRequest
2 голосов
/ 24 сентября 2011

Я знаю, что это, вероятно, не очень хороший стиль Ruby, но я учусь ... что здесь происходит? В частности, почему первая строка моего массива является дубликатом второй строки, когда я думаю, что инициализирую (копирую) значения параметра массива testa в @test, сохраняя все индексы одинаковыми?

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]]

Ответы [ 3 ]

5 голосов
/ 24 сентября 2011

Причиной проблемы, которую вы видите, является то, как вы инициализируете массив.Вы передаете один только что инициализированный массив в вызове метода, который используется в качестве значения для каждой строки.

# 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] 

Так что в вашем методе, когда вы перебираете строки, вы постоянноизменение значений одного и того же массива.

Чтобы исправить это, создайте новый массив для каждой строки, а не 1 массив, на который ссылаются 5 раз.Это может быть выполнено с использованием варианта инициализации блока Array.Что-то вроде:

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

Проверьте документы для более подробного объяснения различных методов инициализации массива.

1 голос
/ 24 сентября 2011

См .: http://www.ruby -doc.org / core / classes / Array.html в Array.new (size, obj)

создается с размерами копийobj (то есть размер ссылается на один и тот же объект)

Объект 'Array.new (размер)' - это один и тот же объект для каждой строки.

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

Или другая реализация вашего кода:

class Test
  def initialize(array)
    @test = array.map{|ar| Array.new(ar) }
  end
end
t = Test.new([[1,2],[3,4]])
0 голосов
/ 23 июля 2018

Вот еще один пример той же проблемы, которая недавно меня поразила:

irb(main):001:0> a = [[0]*3]*2
=> [[0, 0, 0], [0, 0, 0]]
irb(main):002:0> a
=> [[0, 0, 0], [0, 0, 0]]
irb(main):003:0> a[0][1] = 12
=> 12
irb(main):004:0> a
=> [[0, 12, 0], [0, 12, 0]]

Внутренний массив [0,0,0], очевидно, передается по ссылке на внешнюю логику множественной инициализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...