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} };