У меня есть структура данных, которая является хешем, который содержит массив хешей. Я хотел бы достигнуть там и вытащить первый хеш, который соответствует значению, которое я ищу. Я попробовал это:
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} };
Будет не только более понятно, что вы пытаетесь сделать, но и также будет быстрее, потому что он перестанет обрабатывать ваш массив после того, как найдет соответствующий элемент.
Другой способ сделать это:
my $result = (grep {$_->{name} eq 'foo'} @{$hash_ref->{list}})[0];
Обратите внимание, что завитки вокруг первого аргумента grep
в этом случае избыточны, поэтому вы можете избежать затрат на установку и демонтаж блока с помощью
my $result = (grep $_->{name} eq 'foo', @{$hash_ref->{list}})[0];
“List value конструкторы »в perldata документируют индексирование списков:
Значение списка также может иметь индекс, как обычный массив. Вы должны заключить список в круглые скобки, чтобы избежать двусмысленности. Например:
# Stat возвращает значение списка. $ time = (stat ($ file)) [8]; # SYNTAX ERROR HERE. {{1} } $ time = stat ($ file) [8]; # Ой, ЗАБЫЛИ СКРЕБКИ # Найдите шестнадцатеричную цифру. $ hexdigit = ('a', 'b', 'c', 'd', 'e', 'f') [$ digit-10]; # "оператор обратной запятой". return (pop (@foo), pop (@foo)) [0 ];
Насколько я помню, мы получили эту функцию, когда Рэндал Шварц в шутку предложил ее и Чип Зальценберг , который в те дни был мастером по ремонту заплат - реализовал его в тот вечер.
Обновление: Небольшой поиск показывает, что я имел в виду функцию $ coderef -> (@ args)
. Сообщение фиксации даже записывает разговор!