Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl: find if a variable's value matches that in an array

Tags:

arrays

regex

perl

I'm a perl newbie. I have a code in which a variable is loaded with several values during a foreach loop. What I want to do is to perform some operation on that variable only if its in that array. What is the most efficient way to do this in perl as the data I am working on is very large.

A simple example of my question is, say I have an array of fruits I want

@fruits_i_like = qw (mango banana apple);

But I have a $fruit variable in a foreach loop which gets the name of fruits from a data file that has all different types of fruits. How would I pick only those cases of $fruit that are in my @fruits_i_like array?

like image 881
sfactor Avatar asked Oct 29 '10 11:10

sfactor


People also ask

How do you check if a value exists in an array in Perl?

The exists() function in Perl is used to check whether an element in an given array or hash exists or not. This function returns 1 if the desired element is present in the given array or hash else returns 0.

How do I match a string in an array in Perl?

The Perl grep() function is a filter that runs a regular expression on each element of an array and returns only the elements that evaluate as true. Using regular expressions can be extremely powerful and complex. The grep() functions uses the syntax @List = grep(Expression, @array).

What does ~~ mean in Perl?

Just as with the =~ regex match operator, the left side is the "subject" of the match, and the right side is the "pattern" to match against -- whether that be a plain scalar, a regex, an array or hash reference, a code reference, or whatever.

How do you find the index of an array element in Perl?

Perl access array elements Array elements are access by their indexes. The first index has value 0. The last index is $#vals . Array elements can be accessed from the end by using negative indexes.


2 Answers

Perl 5.10 or higher?

use strict;
use warnings;
use 5.10.0;
my @fruits_i_like = qw/mango banana apple/;
my $this_fruit = 'banana';
if ( $this_fruit ~~ \@fruits_i_like ) {
     say "yummy, I like $this_fruit!";
}

Before 5.10:

use strict;
use warnings;
my @fruits_i_like = qw/mango banana apple/;
my $this_fruit = 'banana';
if ( scalar grep $this_fruit eq $_, @fruits_i_like ) {
     print "yummy, I like $this_fruit!\n";
}

The downside is that the whole array is parsed through to find matches. This may not be the best option, in which case you can use List::MoreUtils' any(), which returns true once it matches a value and doesn't continue going through the array.

use strict;
use warnings;
use List::MoreUtils qw/any/;
my @fruits_i_like = qw/mango banana apple/;
my $this_fruit = 'banana';
if ( any { $this_fruit eq $_ } @fruits_i_like ) {
     print "yummy, I like $this_fruit!\n";
}

Happy hacking!

like image 129
mfontani Avatar answered Sep 21 '22 10:09

mfontani


You can use a hash like this :

my %h = map {$_ => 1 } @fruits_i_like;
if (exists $h{$this_fruit}) {
    # do stuff
}

Here is a benchmark that compare this way vs mfontani solution

#!/usr/bin/perl 
use warnings;
use strict;
use Benchmark qw(:all);

my @fruits_i_like = qw/mango banana apple/;
my $this_fruit = 'banana';
my %h = map {$_ => 1 } @fruits_i_like;
my $count = -3;
my $r = cmpthese($count, {
    'grep' => sub {
         if ( scalar grep $this_fruit eq $_, @fruits_i_like ) {
             # do stuff
         }
    },
    'hash' => sub {
        if (exists $h{$this_fruit}) {
             # do stuff
        }
    },
});

Output:

          Rate grep hash
grep 1074911/s   -- -76%
hash 4392945/s 309%   --
like image 22
Toto Avatar answered Sep 23 '22 10:09

Toto