quantik
quantik

Reputation: 816

If statement with multiple conditions in perl

I'm trying to construct an if statement with multiple conditions without being too verbose. Currently I have:

my $string = "Hamburger";
my @string_as_array = ( $string =~ m/.../g );
my $x=(scalar @string_as_array);
for(my $i=0; $i<$x; $i++)   {
    if ($string_as_array[$i] eq "Ham" || $string_as_array[$i] eq "bur") {
        print "CHEESE";
    }
    elsif ($string_as_array[$i] eq "ger")   {
        print "WICH";
    }
    else {
        print $string_as_array[$i];
    }
}
print "\n";

Ideally I'd like something like this for the first if statement if it is possible:

my $string = "Hamburger";
my @string_as_array = ( $string =~ m/.../g );
my $x=(scalar @string_as_array);
for(my $i=0; $i<$x; $i++)   {
    if ($string_as_array[$i] eq "Ham" || "bur") {
        print "CHEESE";
    }
    elsif ($string_as_array[$i] eq "ger")   {
        print "WICH";
    }
    else {
        print $string_as_array[$i];
    }
}
print "\n";

If it's possible.

Upvotes: 3

Views: 9867

Answers (3)

ikegami
ikegami

Reputation: 385839

my %map = (
   'Ham' => 'CHEESE',
   'bur' => 'CHEESE',
   'ger' => 'WICH',
);

say $string =~ s{...}{ $map{$&} // $& }serg;

Other things are much more badly in need simplifying!

The symbol soup

my $x=(scalar @string_as_array);
for (my $i=0; $i<$x; $i++) 

simplifies to

for (my $i=0; $i<@string_as_array; $i++) 

which simplifies to

for my $i (0 .. $#string_as_array)

But you don't actually need the index (just the elements), so replace that with

for my $part (@string_as_array)

or even

for my $part ( $string =~ /.../sg )

That already gives us something cleaner:

for my $part ( $string =~ /.../sg ) {
    if ($part eq "Ham" || $part eq "bur") {
        print "CHEESE";
    }
    elsif ($part eq "ger")   {
        print "WICH";
    }
    else {
        print $part;
    }
}

That said, what we now have begs for a hash lookup.

my %map = (
   'Ham' => 'CHEESE',
   'bur' => 'CHEESE',
   'ger' => 'WICH',
);

for my $part ( $string =~ /.../sg ) {
    print $map{$part} // $part;
}

print("\n");

We could use a while loop instead.

while ( $string =~ /.../sg ) {
    print $map{$&} // $&;
}

print("\n");

We could even switch to a substitution operator.

say $string =~ s{...}{ $map{$&} // $& }serg;

Upvotes: 6

mob
mob

Reputation: 118605

It's possible with regular expression alternation.

if ($string_as_array[$i] =~ /^(?:Ham|bur)$/) {
    ...
}

Upvotes: 2

Hunter McMillen
Hunter McMillen

Reputation: 61512

||, &&, or, and and are all binary operators, meaning they require two operands. Instead you can use grep which accepts a list of things and filters them by some predicate expression:

if ( grep { $string_as_array[$i] eq $_ } qw(Ham bur) ) {
   ...
}

Upvotes: 2

Related Questions