2

I have an array of hashes:

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

and I want to get an array of all the names (to display in a CGI popup menu). I tried using this grep statement:

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

but it just returns an array of hash values...

So I am currently resorting to using a loop to iterate through all the values, pushing them into another array.

Is there a way to speed this up?

4 Answers 4

7

You want map, not 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

But note this doesn't have anything to do with speed, at least not in a significant way, and speed shouldn't be your primary concern; readability should be it. Of course, efficiency is important, but don't let yourself be fooled into thinking that the more concise and cryptic your code the better your program's performance. This is not so. To assess performance, benchmark your programs.

Sign up to request clarification or add additional context in comments.

3 Comments

I know that you are showing all the steps, but you can skip the temporary variable @names: print map $_->{name}, @sports.
@briandfoy - Rather: print for map $_->{name}, @sports - else all sports will end up lumped together in one RugbyFootball. I use print for LIST a lot in combination with -l on the command-line, like: perl -lwe "print for sort keys %main::".
Thanks! I understand your speed argument (in processing terms). I think I could have better described it as 'less typing'. Depending on where I retrieve the data from, means I have two loops in separate places just to create the names array. With the map I can do it in one place
0
my @sports;
push @sports, { id=>1, name=>'Rugby' };
push @sports, { id=>2, name=>'Football' };
foreach(@sports){
  push @names, $_->{'name'};
}
foreach(@names){
  print "$_\n";
}

Ah, sorry - reread your post. TBH, however you write it, I suspect that internally a loop will be taking place anyway. Are you sure you're not trying to prematurely optimise? Is there a performance issue?

Comments

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

infact you can also use map function to loop through

Comments

0

The solution is trivial if you've really hard coded the populating of @sports as in your example:

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

This avoids the second loop altogether.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.