grep is your friend

Grep is another Perl's great built in function, one of the things I use it most is to check if I can find an element on a list. For example, instead of something like

    my $found = 0;
    foreach (@list) {
        $search eq $_ and $found++;

I prefer to use something like:

    my $found = grep {$search eq $_} @list;

Code is simpler and more elegant, there's no significant performance from using one or another, although grep seems to actually run faster if you want to squeeze all the crumbs:

find_with_for  28818/s             --            -5%
find_with_grep 30211/s             5%             --

Grep can be used to filter lists on elements very nicely too, for example, imagine you have a list of users and want to filter the users that are older than 18, just:

    my @users_over_18 = grep { $_->{'age'} > 18 } @users;

All and all, grep is great.


List::Util::first does the same thing but stops processing at the first element (and only returns that first element). The only gotcha is if you are trying to find undef in the list.

import List::Util qw(first);
my $found = first {$search eq $_} @list;

I agree, the second sample is so much nicer than the first. We sometimes hear that grep and map make code harder to read, but done correctly, I think the opposite is true.

Note that if you don't really want to count the number of times the element appears, but just find out if it appears at all, then Perl's smart-match operator does this.

    my $found = $search ~~ @list;

This requires Perl 5.10 or newer.

@Jeff: first returns the first element, which may be a false value. If you want to know if any value matches efficiently but you don't case how many, List::MoreUtils::any or smartmatch is what you want.

Leave a comment

About smash

user-pic I blog about Perl.