Ответ 1
my ($result) = grep {$_->{name} eq 'foo'} @{$hash_ref->{list}};
... должен выполнять эту работу. Возьмите возврат из grep в контексте списка, но не присваивайте ни одно из значений, отличных от первого.
У меня есть структура данных, которая является хешем, который содержит массив хэшей. Я бы хотел туда добраться и вытащить первый хэш, который соответствует значению, которое я ищу. Я пробовал это:
my $result = shift grep {$_->{name} eq 'foo'} @{$hash_ref->{list}};
Но это дает мне эту ошибку: Type of arg 1 to shift must be array (not grep iterator).
Я перечитал perldoc для grep
, и я думаю, что У меня все имеет смысл. grep
возвращает список, не так ли? Это неправильный контекст?
Я сейчас использую временную переменную, но я хотел бы выяснить, почему это не работает.
my ($result) = grep {$_->{name} eq 'foo'} @{$hash_ref->{list}};
... должен выполнять эту работу. Возьмите возврат из grep в контексте списка, но не присваивайте ни одно из значений, отличных от первого.
Я думаю, что лучший способ написать это:
use List::Util qw/first/;
my $result = first { $_->{name} eq 'foo' } @{ $hash_ref->{list} };
Не только будет более ясно, что вы пытаетесь сделать, но и быстрее, потому что он остановит grepping вашего массива, как только он найдет соответствующий элемент.
Другой способ сделать это:
my $result = (grep {$_->{name} eq 'foo'} @{$hash_ref->{list}})[0];
Обратите внимание, что в этом случае завивки вокруг первого аргумента grep
избыточны, поэтому вы можете избежать затрат на установку блока и затраты на разрывы с помощью
my $result = (grep $_->{name} eq 'foo', @{$hash_ref->{list}})[0];
"Конструкторы значений списка" в perldata документы подписи списков:
Значение списка также может быть индексировано как обычный массив. Вы должны поместить список в круглые скобки, чтобы избежать двусмысленности. Например:
# Stat returns list value. $time = (stat($file))[8]; # SYNTAX ERROR HERE. $time = stat($file)[8]; # OOPS, FORGOT PARENTHESES # Find a hex digit. $hexdigit = ('a','b','c','d','e','f')[$digit-10]; # A "reverse comma operator". return (pop(@foo),pop(@foo))[0];
Как я помню, мы получили эту функцию, когда Рэндал Шварц в шутку предложили ее, и Chip Salzenberg, который в то время был патч-машиной, - реализовал его в тот вечер.
Обновление: Немного поиска показывает, что я имел в виду $coderef->(@args)
. Сообщение фиксации даже регистрирует разговор!