Как вы сопоставляете массив [key1, val1] с хэшем {key1 => val1} в perl?
Проблема в том, что у меня есть массив, который содержит пары значений ключей в качестве элементов в массиве, и я должен каким-то образом разделить их на пары значений ключей => в хэше.
Моя первая попытка в этом работает, но я думаю, что это довольно грязно - я должен получить каждый другой элемент массивов, а затем фильтровать, чтобы найти принятые ключи для создания хэша с
my $HASH;
my $ARRAY = [ key1, val1, key2, val2, __key3__, val3, __key4__, val4 ];
my @keys = map{ $ARRAY[ $_*2 ] } 0 .. int($#ARRAY/2);
my @vals = map{ $ARRAY[ $_*2+1 ] } 0 .. int($#ARRAY/2);
my $i = 0;
#filter for keys that only have __key__ format
for $key (@keys){
if( $key && $key =~ m/^__(.*)__$/i ){
$HASH{$1} = $vals[$i];
}
$i++;
}
# only key3 and key4 should be in $HASH now
Я нашел этот пример кода , который, как мне кажется, близок к тому, что я ищу, но я не могу понять, как реализовать нечто подобное над массивом, а не перебирание строк текстового файла:
$file = 'myfile.txt'
open I, '<', $file
my %hash;
%hash = map { split /s*,s*,/,$_,2 } grep (!/^$/,<I>);
print STDERR "[ITEM] $_ => $hash{$_}n" for keys %hash;
Может ли кто-нибудь из вас, гуру perl, помочь мне понять, как лучше всего это сделать? Даже если бы я мог каким-то образом объединить все элементы в строку, а затем разделить каждый второй символ пробела-это тоже могло бы сработать, но пока я застрял!5 ответов:
Это очень просто:
use strict; use warnings; use YAML; my $ARRAY = [qw(key1 val1 key2 val2 __key3__ val3 __key4__ val4)]; my $HASH = { @$ARRAY }; print Dump $HASH;
Вывод:
C:\Temp> --- __key3__: val3 __key4__: val4 key1: val1 key2: val2
В найденном примере кода часть
<I>
считывает весь файл и возвращает список в grep. grep обрабатывает список и передает его на карту. Затем Map создает свой собственный список, и этот список присваивается хэшу.При назначении списка хэшу предполагается, что список является четным списком пар ключ/значение.
Не имеет значения, откуда берется этот список, он может быть результатом команды map, grep или split. Это может быть прямо из файла, это может быть ... хранится в массиве.
Ваша строка:
my $HASH = ();
Не делает ничего полезного. Написание
my $HASH;
точно такое же.В этой точке
$HASH
не определено. Когда у вас есть неопределенное значение и вы разыменуете его как хэш,%$HASH
, неопределенное значение станет хэшем.Вы можете сделать это явным, написав:
my $HASH = {}; # note the curly braces and not parens
Если у вас есть список пар значений ключей в массиве:
%$HASH = @array;
Если у вас есть список ключей и список значения:
@$HASH{@keys} = @values;
В соответствии с вашим вопросом, Вот один простой способ создания хэша из массива при фильтрации значений:
my $HASH = {}; my $ARRAY = [ qw(key1 val1 key2 val2 __key3__ val3 __key4__ val4) ]; {my @list = @$ARRAY; # make a copy since splice eats the list while (my ($k, $v) = splice @list, 0, 2) { if ($k =~ /^__(.+)__$/) { $$HASH{$1} = $v } } } use Data::Dumper; print Dumper($HASH);
Который печатает:
Если вы хотите сделать это все в одной строке, вы можете использовать функцию$VAR1 = { 'key4' => 'val4', 'key3' => 'val3' };
mapn
из моего модуля List::Gen, которая является функцией, подобнойmap
, но которая позволяет вам перемещаться по списку с любым размером шага, а не только по одному элементу за раз.use List::Gen 'mapn'; %$HASH = mapn {/^__(.+)__$/ ? ($1, $_[1]) : ()} 2 => @$ARRAY;
Я не знал, что вы можете сбросить массив, и хэш поймет это.Нет ничего волшебного в значениях, которые приходят из массива. Гашишу тут нечего выяснять.
Если вы назначите хэшу список, он очистит хэш, а затем обработает список как список пар ключ-значение, из которых нужно инициализировать хэш. Итак
%hash = ( foo => 1, bar => 2 );
Эквивалентно
my @anon = ( foo => 1, bar => 2 ); %hash = (); while (@anon) { my $key = shift(@anon); my $val = shift(@anon); $hash{$key} = $val; }
Список есть список. Не имеет значения, был ли он произведен с помощью списка / запятой op
x => "foo", y => "bar"
Используя
qw()
qw( x foo y bar )
Или с помощью массива
@array
Таким образом, это означает, что все нижеследующие являются одинаковыми.
%hash = ( x => "foo", y => "bar" ); %hash = qw( x foo y bar ); %hash = @array; # Assuming @array contains the correct values.
И так же
$hash = { x => "foo", y => "bar" }; $hash = {qw( x foo y bar )}; $hash = { @array }; # Assuming @array contains the correct values.
Поскольку ваш конкретный случай уже получил ответ, я подумал, что отвечу на случай того, что я взял ваш вопрос, чтобы задать. Я ожидал увидеть массив пар, подобных
[ key => $value ]
, и что вы хотите поместить либо в массив хэшей, либо в хэш:Этот ответ звучит так:
Только я беру каждый из них и" взрываю " их, разыменовывая (my %hash = map { @$_ } [[ key1 => $value1 ], [ key2 => $value2 ], ... ]; my @ha = map {; { @$_ } } [[ key1 => $value1 ], [ key2 => $value2 ], ... ]; my %hash = @$array_ref_of_values;
@$_
).