2012-05-16 2 views
2

У меня есть массив хэшей:В Perl, как я могу преобразовать массив хэшей в массив значений?

my @sports; 
push @sports, { id=>1, name=>'Rugby' }; 
push @sports, { id=>2, name=>'Football' }; 

, и я хочу, чтобы получить массив всех имен (для отображения в контекстном меню CGI). Я попытался с помощью этого Grep заявления:

my @names = grep { $_->{name} } @sports; 

, но он просто возвращает массив значений хэша ...

Так я в настоящее время прибегаю к использованию цикла для перебора всех значений, толкая их в другую массив.

Есть ли способ ускорить это?

ответ

7

Вы хотите map, не grep:

use strict; 
use warnings; 
my @sports; 
push @sports, { id=>1, name=>'Rugby' }; 
push @sports, { id=>2, name=>'Football' }; 
my @names = map $_->{name}, @sports; 
print for @names; 
D:\temp> perl -l m.pl 
Rugby 
Football

Но заметьте, это не имеет ничего общего со скоростью, по крайней мере существенным образом, и скорость не должна быть вашей основной беспокойство; читабельность должна быть такой. Разумеется, эффективность важна, но не позволяйте себе обманывать мысль о том, что чем более кратким и загадочным ваш код, тем лучше производительность вашей программы. Это не так. To assess performance, benchmark your programs.

+0

Я знаю, что вы показываете все шаги, но вы можете пропустить временную переменную '@ names':' print map $ _-> {name}, @ sports'. –

+0

@briandfoy - Скорее: 'print for map $ _-> {name}, @ sports' - иначе все виды спорта будут объединены в один« RugbyFootball ». Я использую 'print for LIST' много в комбинации с' -l' в командной строке, например: 'perl -lwe 'print для ключей сортировки% main ::" '. – Lumi

+0

Спасибо! Я понимаю ваш аргумент скорости (в терминах обработки). Думаю, я мог бы лучше описать это как «меньше набрав». В зависимости от того, где я извлекаю данные, значит, у меня есть две петли в отдельных местах, чтобы создать массив имен. С картой я могу сделать это в одном месте – skeniver

0
my @sports; 
push @sports, { id=>1, name=>'Rugby' }; 
push @sports, { id=>2, name=>'Football' }; 
foreach(@sports){ 
    push @names, $_->{'name'}; 
} 
foreach(@names){ 
    print "$_\n"; 
} 

А, извините - перечитайте сообщение. TBH, однако вы пишете его, я подозреваю, что внутри цикла будет проходить все равно. Вы уверены, что не пытаетесь преждевременно оптимизировать? Есть ли проблема с производительностью?

0
for my $i (0 .. $#sports) { 
    print "$sports[$i]{name} \n";  
} 

Infact вы можете также использовать функцию карты Переберите

0

Решение тривиально, если вы на самом деле трудно закодировал заселение @sports, как в вашем примере:

my (@sports, @names); 
push @sports, { id=>1, name=>'Rugby' }; 
push @names, 'Rugby'; 
push @sports, { id=>2, name=>'Football' }; 
push @names, 'Football'; 

Это позволяет избежать вторая петля вообще.

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