Что это значит, когда вы пытаетесь напечатать массив или хеш с помощью Perl и получаете Array (0xd3888)? - PullRequest
13 голосов
/ 18 мая 2010

Что это значит, когда вы пытаетесь напечатать массив или хеш, и вы видите следующее; Массив (0xd3888) или HASH (0xd3978)?

Пример

код

my @data = (  
['1_TEST','1_T','1_TESTER'],  
['2_TEST','2_T','2_TESTER'],  
['3_TEST','3_T','3_TESTER'],  
['4_TEST','4_T','4_TESTER'],  
['5_TEST','5_T','5_TESTER'],  
['6_TEST','6_T','^_TESTER']  
);  

foreach my $line (@data) {  
   chomp($line);  
   @random = split(/\|/,$line);  
   print "".$random[0]."".$random[1]."".$random[2]."","\n";  
}  

РЕЗУЛЬТАТ

ARRAY(0xc1864)  
ARRAY(0xd384c)  
ARRAY(0xd3894)  
ARRAY(0xd38d0)  
ARRAY(0xd390c)  
ARRAY(0xd3948)  

Ответы [ 3 ]

18 голосов
/ 18 мая 2010

Трудно сказать, имели ли вы в виду это или нет, но причина, по которой вы получаете ссылки на массивы, заключается в том, что вы не печатаете то, что вы думаете.

Вы начали правильно, перебирая 'строки' @data с помощью:

foreach my $line (@data) { ... }

Однако следующая строка запрещена. Кажется, что вы путаете текстовые строки со структурой массива. Да, каждая строка содержит строки, но Perl рассматривает @data как массив, а не строку.

split используется для преобразования строк в массивы. Он не работает с массивами! То же самое относится и к chomp (с несущественным исключением).

Вам нужно заменить содержимое цикла foreach на следующее:

foreach my $line (@data) {

    print $line->[0].", ".$line->[1].", ".$line->[2]."\n";
}

Вы заметите обозначение ->, которое есть по причине. $line относится к массиву. Это не сам массив. Стрелки -> обращаются к массиву, позволяя получить доступ к отдельным элементам массива, на которые ссылается $line.

Если вам не нравится идея делать стрелки с помощью стрелок (а большинство новичков обычно этого не делают), вы можете создать временный массив, как показано ниже, и использовать его вместо этого.

foreach my $line (@data) {

    my @random = @{ $line };
    print $random[0].", ".$random[1].", ".$random[2]."\n";
}

OUTPUT

1_TEST, 1_T, 1_TESTER
2_TEST, 2_T, 2_TESTER
3_TEST, 3_T, 3_TESTER
4_TEST, 4_T, 4_TESTER
5_TEST, 5_T, 5_TESTER
6_TEST, 6_T, ^_TESTER

Однострочник может выглядеть примерно так: print "@$_\n" for @data; (что немного OTT), но если вы хотите просто напечатать массив, чтобы посмотреть, как он выглядит (скажем, в целях отладки), я бы порекомендовал использовать модуль Data::Dump, который довольно красиво печатает массивы и хэши, не беспокоясь об этом.

Просто поставьте use Data::Dump 'dump'; в начале вашего скрипта, а затем dump @data;. Так просто!

4 голосов
/ 18 мая 2010

Это означает, что у вас нет массива; у вас есть ссылка на массив.

Обратите внимание, что массив указывается в круглых скобках - как список; Когда вы используете квадратную скобку, вы создаете ссылку на массив.

foreach my $line (@data)
{
    my @array = @$line;
    print "$array[0] - $array[1] - $array[2]\n";
}

Иллюстрируя разницу:

my @data = (
['1_TEST','1_T','1_TESTER'],
['2_TEST','2_T','2_TESTER'],
['3_TEST','3_T','3_TESTER'],
['4_TEST','4_T','4_TESTER'],
['5_TEST','5_T','5_TESTER'],
['6_TEST','6_T','^_TESTER']
);

# Original print loop
foreach my $line (@data)
{
    chomp($line);
    @random = split(/\|/,$line);
    print "".$random[0]."".$random[1]."".$random[2]."","\n";
}

# Revised print loop
foreach my $line (@data)
{
    my @array = @$line;
    print "$array[0] - $array[1] - $array[2]\n";
}

выход

ARRAY(0x62c0f8)
ARRAY(0x649db8)
ARRAY(0x649980)
ARRAY(0x649e48)
ARRAY(0x649ec0)
ARRAY(0x649f38)
1_TEST - 1_T - 1_TESTER
2_TEST - 2_T - 2_TESTER
3_TEST - 3_T - 3_TESTER
4_TEST - 4_T - 4_TESTER
5_TEST - 5_T - 5_TESTER
6_TEST - 6_T - ^_TESTER
0 голосов
/ 19 мая 2010

Вы печатаете ссылку на хеш или массив, а не на содержимое этого.

В конкретном коде, который вы описываете, я, кажется, вспоминаю, что Perl автоматически превращает переменную индексации цикла foreach (my $line в вашем коде) в "псевдоним" (своего рода ссылка, я думаю) значения на каждом этапе цикла.

Итак, $line - это ссылка на @data[x] ..., которая на каждой итерации представляет собой некоторый массив. Чтобы добраться до одного из элементов @data[0], вам понадобится символ $ (поскольку элементы массива в @data[0] являются скалярами). Однако $line[0] является ссылкой на некую несуществующую пакетную / глобальную переменную (use warnings; use strict; скажет вам об этом, кстати).

[Отредактировано после того, как Эфир указал на мое невежество] @data - список ссылок на анонимные массивы; каждый из которых содержит список скаляров. Таким образом, вы должны использовать вид явного разыменования, который я опишу ниже:

Что вам нужно, это что-то вроде:

print ${$line}[0], ${$line}[1], ${$line}[2], "\n";

... обратите внимание, что $ {xxx} [0] обеспечивает разыменование xxx, затем выполняется индексация по результату разыменования, который затем извлекается как скаляр.

Я также тестирую это:

print $$line[0], $$line[1], $$line[2], "\n";

... и, похоже, работает. (Однако я думаю, что первая форма более четкая, даже если она более многословна).

Лично я записываю это на счет еще одной ошибки в Perl.

[Дальнейшая редакция] Я все еще считаю это "гочей". Такие вещи, как это, и тот факт, что большинство ответов на этот вопрос были технически правильными, и в то же время совершенно не демонстрировали каких-либо усилий, чтобы реально помочь оригинальному постеру, еще раз напомнили мне, почему я перешел на Python так много лет назад. Размещенный мною код работает, конечно, и, вероятно, выполняет то, что пытался ФП. Мое объяснение было полностью неверным. Я увидел слово «псевдоним» на странице руководства `perlsyn` и вспомнил, что где-то там была какая-то прикольная семантика; поэтому я полностью упустил ту часть, которая [...] создает анонимную ссылку. Если вы не пьете из Perl Kool-Aid в глубоких черновиках, даже самый простой код не может быть объяснен.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...