Почему двумерный массив в Perl печатается неправильно? - PullRequest
0 голосов
/ 16 июля 2009

Работа с двумерными массивами в Perl доставляет мне головную боль. Во всяком случае, мой вопрос заключается в следующем:

У меня есть цикл, который помещает массив, скажем, @twoOneArray, в другой массив, скажем, @twoDimArray, и затем сбрасывается до начала следующей итерации цикла, а затем снова помещается в @twoDimArray с новым набором значений. Когда я печатаю этот @twoDimArray, используя:

print Dumper \@twoDimArray;

это дает вывод

OUTPUT

$VAR1 = [

      [

        'BB',

        'AA',

        'AA'
       ],
       $VAR1->[0],
       $VAR1->[0],
       $VAR1->[0]
     ];

или используя петли

for (my $i=0; $i<4; $i++){
    for (my $j=0; $j<4; $j++){
         print "$twoDimArray[$i][$j] \n";
    }
}

данные дублируются.

OUTPUT

Строка = 0 BB AA AA

Строка = 1 BB AA AA

Строка = 2 BB AA AA

Строка = 3 BB AA AA

и т. Д.

Я не могу понять, почему оба способа вывода идут неправильно. Если я печатаю @twoDimArray каждый раз (до перехода к следующей итерации цикла, т. Е. После использования функции push), @twoOneArray вставляется, тогда значения кажутся хорошими и не повторяются, но печать за один раз, кажется, дает ошибка. Подобный вопрос был задан здесь , но я не уверен, имеет ли это смысл для меня. Есть предложения?

Код для построения 2D-массива:

for ($k = 1; $k <= $counter; $k++){
        @twoOneArray = (); #reset it when loop starts again
        for ($j = 0; $j <= $colsInArray; $j++){
        #do stuff to create @twoOneDim
        }
        push @twoDimArray, \@twoOneArray;
        #if I print @twoDimArray if prints fine, with the exact values intact
}

print Dumper \@twoDimArray; #if I print it here it messes up
print "\n";

Ответы [ 4 ]

10 голосов
/ 16 июля 2009

Вывод Data :: Dumper говорит мне, что ваша проблема не в печати массива. Data :: Dumper никогда не лжет (или редко).

Пожалуйста, покажите нам код, который вы использовали для построения массива. Я уверен, что ошибка в этом коде где-то.

UPDATE:

Теперь, когда вы добавили код, который создает массив, я вижу, что вы попали в злую ловушку: вы добавляете ссылку на @twoOneArray в свой «внешний» массив. Но ссылка всегда будет одинаковой каждый раз в вашем цикле. Измените свой код следующим образом:

for ($k = 1; $k <= $counter; $k++){
        my @twoOneArray; # REALLY reset it when loop starts again
        for ($j = 0; $j <= $colsInArray; $j++){
            #do stuff to create @twoOneDim
        }
        push @twoDimArray, \@twoOneArray;
}

.. и это должно работать.

4 голосов
/ 16 июля 2009

Другие пользователи ответили на ваш вопрос. Я хотел бы добавить, что вывод Data::Dumper полезен для выявления таких проблем: элемент [1] вашего массива сбрасывается как $VAR1->[0] - другими словами, это ссылка на те же базовые значения данных, которые хранятся в [0] элемент.

4 голосов
/ 16 июля 2009

Вы сделали что-то вроде этого:

@a = (1, 2, 3);
push @b, \@a;

@a = (2, 3, 4);
push @b, \@a;

# ...

Проблема в том, что вы нажимаете @b a ссылка на @a. Все ссылки указывают на одно и то же @a. Data::Dumper говорит вам это со своей $VAR->[0] вещью.

Вам нужно сделать что-то вроде:

$a = [ 1, 2, 3 ];
push @b, $a;

$a = [ 2, 3, 4] ;
push @b, $a;

# ....

Таким образом, синтаксис [ ... ] arrayref будет каждый раз создавать новый ссылочный массив.

Я предлагаю внимательно прочитать perlreftut и perlref.

edit: Я вижу, вы опубликовали свой код, и да, вы делаете мой пример неработающего кода. Перейдите на использование синтаксиса [ ... ], и все будет в порядке.

0 голосов
/ 16 июля 2009

Если вам нужен массив массивов, вы должны выдвигать ссылки на массивы, например,

my @a = qw(1 2 3 4 5 6 7 8);
my @b = qw(a b c d e f g h);
my @aOfa;

push(@aOfa, \@a);
push(@aOfa, \@b);
...