Perl Как мне получить массив из хэша массивов?

Я довольно новичок в Perl, так что прости меня, если это кажется простым вопросом...

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

%HoA = a hash of arrays
$key = some key in the hash

foreach $nextItem (@HoA{$key}) {
  do a bunch of stuff with $nextItem
}

Когда я делаю это, $nextItem всегда равен размеру массива, и цикл выполняется только один раз. Я попытался напечатать следующее:

@HoA{$key}
$HoA{$key}
@$HoA{$key}

Первые два дают мне скалярный размер, а третий ничего не дает... что мне здесь не хватает?

ОБНОВЛЕНИЕ: мне интересно, действительно ли моя проблема заключается в том, как я добавляю массивы к хешу. Вот что я делаю:

@HoA{$key} = split(/ /, $list);

Это вставляет массив в хэш или размер массива в хэш?

ОБНОВЛЕНИЕ 2: я попробовал следующий блок кода:

my $key = "TEST";
my %HoA = ();
my @testarray = (1, 2, 3);
@HoA{$key} = @testarray;
print Dumper(%HoA);

Вот вывод:

$VAR1 = 'TEST';
$VAR2 = 1;

Почему он вставляет только первое значение массива?

4 ответа

Решение

Попробуйте ссылаться на ваш массив следующим образом:

%HoA = a hash of arrays
$key = some key in the hash

foreach $nextItem (@{$HoA{$key}}) {
  do a bunch of stuff with $nextItem
}

Вы берете ссылку на массив в $HoA{$key} и сделать его массивом.

Изменить: Для вашего обновления, я думаю, вы получите то, что вы хотите, если вы сделаете это так:

@{$HoA{$key}} = split(/ /, $list);

или вы можете сделать

push(@{$HoA{$key}}, split(/ /, $list);

Например:

my $list = "fred joe brown sam";
my %HoA = ();
my $key = "jacob";
@{$HoA{$key} = split(/ /, $list);
foreach my $item (@{$HoA{$key}})
{
    print "Test item: $nextItem\n";
}

You will get:
Test item: fred
Test item: joe
Test item: brown
Test item: sam

Редактировать: Добавить use strict; в начало вашей программы. В основном вы пытаетесь использовать HoA в качестве массива, когда у вас есть определенный хэш. Вы неправильно ссылаетесь на содержимое своего хэша. Чтобы сделать это правильно, вам действительно нужно иметь $ между @ а также HoA, Perl не печатает и позволит вам убить себя, если вы этого не сделаете use strict;, Отрывок из Орейли может прояснить некоторые вещи.

my @testarray это массив
my %hash это хеш
$hash{$el1} = \@array является хеш-элементом, который имеет значение ссылки на массив
@{$hash{$el1}} = @array это хеш-элемент, который содержит массив

Каждая запись в вашем хэше является ссылкой на массив. Например:

$my_hash{$key}

является ссылкой на массив, а не массив. $my_hash{$key} просто указывает на область в памяти, где живет этот массив. Чтобы разыменовать его, вы помещаете символ массива впереди:

@{ my_hash{$key} }

Когда мы начинаем говорить об элементах, все становится немного неприятнее:

${ my_hash{$key} }[0]

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

$my_hash{$key}->[0];

Это точно так же, как и выше, но проще для понимания синтаксиса. Иногда проще использовать промежуточные переменные просто для того, чтобы вы могли ссылаться на вещи без разыменования:

my %hash_of_array_refs;

foreach my $key (sort keys %hash_of_array_refs) {
    my @array = @{ $hash_of_array_refs{$key} };    #Dereference
    foreach my $element (@array) {                 #Much easier to read and understand
        say "First element is $array[0]";
        say "last element is $array[$#array]";
        say "This element: $element";
    }
}

Без разыменования вы получите это:

my %hash_of_array_refs;

foreach my $key (sort keys %hash_of_array_refs) {
    foreach my $element (@{ $hash_of_array_refs{$key} } ) {                 #Much easier to read and understand
        say "First element is " . $hash_of_array_refs->[0];
        say "last element is " . $hash_of_array_refs->[$#{ $hash_of_array_refs{key} } ]";
        say "This element: $element";
    }
}
@array

Как вы получаете массив, так

@{ $array_ref }

является эквивалентом ссылки на массив.

$HoA{$key}

это ссылка на массив, так

@{ $HoA{$key} }

это тот массив.

for my $nextItem (@{ $HoA{$key} }) 

"Почему он вставляет только первое значение массива?"

Вам нужно поместить ссылку на ваш массив в хеш, поставив перед ним обратную косую черту:

$HoA{$key} = \@testarray;

Затем, когда вы извлекаете его из хэша, вы разыменовываете:

@testarray = @{ $HoA{$key} };
Другие вопросы по тегам