2010-06-15 3 views
7

Предположим, что в Perl у меня есть список хеш-ссылок, и каждый из них должен содержать определенное поле, скажем, foo. Я хочу создать список, содержащий все сопоставления foo. Если есть хеш, который не содержит foo, процесс должен завершиться неудачно.Perl, получить все значения хэша

@hash_list = (
{foo=>1}, 
{foo=>2} 
); 

my @list =(); 
foreach my $item (@hash_list) { 
    push(@list,$item->{foo}); 
} 

#list should be (1,2); 

Есть ли более сжатый способ сделать это в Perl?

+1

Я просто хотел уточнить, что вы не создаете список сопоставлений, вы создаете список, состоящий из каждого хэша 'foo' значение., А ваш пример кода не имеет ничего общего с« процессом сбоя », поэтому вы 'не просто попросить более кратким. –

+1

В общем: всякий раз, когда вы обнаруживаете, что выполняете 'foreach ... {... push ..}', вы можете сделать код короче и проще с помощью map или grep. – Ether

ответ

6

Да. Там есть.

my @list = map { 
    exists $_->{foo} ? $_->{foo} : die 'hashed lacked foo' 
    } 
    @hash_list 
; 
+0

для сложных выражений карты, как правило, легче читать с использованием синтаксиса блока, а не голым выражением –

+0

, что лучше +1, я использую голый синтаксис все время для коротких выражений, вероятно, единственный длинный, который не получить блок в случае карты, которая возвращает arrayref: 'map [...] => ...' –

0
if (@hash_list != grep { exists $_->{foo} } @hash_list) { 
    # test failed 
} 
1

ответ Эвана близок, но будет возвращать hashrefs вместо значения обув.

my @list = map $_->{foo} grep { exists $_->{foo} } @hash_list 
+0

Да, я исправил это. и я также сделал это умирать, есть разрыв между его кодом и его вопросом. Вы также можете сделать это с помощью одного цикла. –

2

Вы можете использовать функцию карты для этого:

@hash_list = (
{foo=>1}, 
{foo=>2} 
); 

@list = map($_->{foo}, @hash_list); 

карта применяет функцию в первом аргументе над всем элементом второго аргумента.

grep также круто фильтрует элементы в списке и работает одинаково.

Смежные вопросы