Почему сдвиг Perl жалуется, что 'Тип аргумента 1 для смещения должен быть массивом (не 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 возвращает список, правильно? Это находится в неправильном контексте?

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

10
задан brian d foy 28 March 2010 в 22:31
поделиться

3 ответа

Список не является массивом .

my ($result) = grep {$_->{name} eq 'foo'} @{$hash_ref->{list}};

… тем не менее, должен сработать. Возьмите возврат из grep в контексте списка, но не присваивайте никаких значений, кроме первого.

18
ответ дан 3 December 2019 в 14:06
поделиться

Я думаю, что лучше написать это так:

use List::Util qw/first/;

my $result = first { $_->{name} eq 'foo' } @{ $hash_ref->{list} };

Будет не только более понятно, что вы пытаетесь сделать, но и также будет быстрее, потому что он перестанет обрабатывать ваш массив после того, как найдет соответствующий элемент.

17
ответ дан 3 December 2019 в 14:06
поделиться

Другой способ сделать это:

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) . Сообщение фиксации даже записывает разговор!

2
ответ дан 3 December 2019 в 14:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: