cosmicperl has asked for the wisdom of the Perl Monks concerning the following question:

Hi All,
  I was just writing an if statement that looked something like:-
if ($var eq "a" || $var eq "b" || ... and so on
I'm sure there is a much shorter way to do it. I know I could use grep or a regexp, but I'm thinking there is a more efficient way to do it...
Help much appreciated :)

Lyle

Update: I was just looking through my previous posts and realized I'd posed an almost identical question 3 years ago! To which there were many solutions posted: 516797 I like the 'any' solution best.

Replies are listed 'Best First'.
Re: long if statements... What's the best way?
by kyle (Abbot) on Apr 02, 2008 at 15:59 UTC

    If you're really checking for $var being eq to one of many elements, a hash would work.

    my %look_for = map { $_ => 1 } qw( a b ... ); if ( $look_for{ $var } ) { }

    That said, I don't see anything wrong with using a regular expression, if it does what you want. I'd only think grep is a problem if you have a huge number of items to check. Maybe you want List::Util::first here?

Re: long if statements... What's the best way?
by Narveson (Chaplain) on Apr 02, 2008 at 16:18 UTC

    Don't worry about performance just yet. Write something that is easy for you to maintain in case you change the list of alternatives.

    my @alternatives = qw(a b etc); # add more by just typing them if (grep {$_ eq $var} @alternatives) {}
Re: long if statements... What's the best way?
by wade (Pilgrim) on Apr 02, 2008 at 15:59 UTC
    When something looks like that, I use a regex:
    if ($var =~ /^[ab...]$/)
    --
    Wade
Re: long if statements... What's the best way? (STRING ~~ ARRAY)
by lodin (Hermit) on Apr 02, 2008 at 19:17 UTC

    If you have Perl 5.10 you can do

    if ($var ~~ [ 'a', 'b', ... ]) { ... }
    or
    my @ok = ('a', 'b', ...); if ($var ~~ @ok) { ... }
    This is more efficient than grep because it doesn't try to match every element.

    In earlier versions you can do

    my %ok = map { $_ => 1 } 'a', 'b', ...; if ($ok{$var}) { ... }

    lodin

Re: long if statements... What's the best way?
by nedals (Deacon) on Apr 02, 2008 at 17:26 UTC

    Similar to wade's solution, but with multi-character comparision

    if ($var=~/^(apple|pear|orange)$/) {....
Re: long if statements... What's the best way?
by casiano (Pilgrim) on Apr 02, 2008 at 19:14 UTC
    Just one more way to do it: use first from List::util

    lhp@nereida:~/Lperl/src/cookbook/ch16$ perl -wde 0 main::(-e:1): 0 DB<1> use List::Util qw(first) DB<2> $var = 'd' DB<3> print "Found $var\n" if (first { $_ eq $var } qw{a e g h d r}) Found d DB<4> $var = 'x' DB<5> print "Found $var\n" if (first { $_ eq $var } qw{a e g h d r}) DB<6>
    Cheers

    Casiano

      any would make more sense in this context. Otherwise the end result is the same.

      Be aware of false strings that match.

      use List::Util 'first'; my $var = '0'; if (first { $_ eq $var } $var) { print "Found.\n"; } else { print "Not found.\n"; } __END__ Not found.
      You could solve this by using defined in this particular case, but it's not a general solution. As Herkum says, any from List::MoreUtils is a better alternative in the general case.

      lodin

Re: long if statements... What's the best way?
by locked_user sundialsvc4 (Abbot) on Apr 02, 2008 at 21:53 UTC

    I agree with the general sentiment that clarity and maintainability trump any (mis-guided) concerns for “efficiency.”

    Any Perl code that you write is going to be compiled into some kind of intermediate-format, which is what the computer actually executes. You have no control over that. What does matter, both to you and to those who'll come back from your funeral, is that the meaning of your code is abundantly clear and that it is drop-dead easy to maintain. (A good thing, since you just dropped dead. Oops.)   ;-)

Re: long if statements... What's the best way?
by dragonchild (Archbishop) on Apr 02, 2008 at 18:42 UTC
    Use a subroutine.

    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re: long if statements... What's the best way?
by njweatherman (Sexton) on Apr 02, 2008 at 16:25 UTC
    You can try using an if else combination.
    if ($var eq "a") {
    print "Test number one";
    }
    elsif ($var eq "b") {
    print "test two";
    }
    else {
    print "test three";
    }

      Using the double pipe ("||") already short circuits testing. In this expression:

      ( $var eq 'a' || $var eq 'b' || $var eq 'c' )

      ...If it turns out that $var eq 'a', the other two conditions are not checked. If $var eq 'b', then only the first two conditions will be checked and not the third.

      Moreover, it does not appear that the OP wants to take different actions for the different values, so having separate blocks for each value found doesn't make sense.