Jaron787
Jaron787

Reputation: 560

Perl searching for string contained in array

I have an array with the following values:

push @fruitArray, "apple|0";
push @fruitArray, "apple|1";
push @fruitArray, "pear|0";
push @fruitArray, "pear|0";

I want to find out if the string "apple" exists in this array (ignoring the "|0" "|1")

I am using:

$fruit = 'apple';
if( $fruit ~~ @fruitArray ){ print "I found apple"; }

Which isn't working.

Upvotes: 4

Views: 1363

Answers (5)

G. Cito
G. Cito

Reputation: 6378

You can get close to the smartmatch sun without melting your wings by using match::simple:

use match::simple;

my @fruits = qw/apple|0 apple|1 pear|0 pear|0/;
$fruit = qr/apple/ ;

say "found $fruit" if $fruit |M| \@fruits ; 

There's also a match() function if the infix [M] doesn't read well.

I like the way match::simple does almost everything I expected from ~~ without any surprising complexity. If you're fluent in perl it probably isn't something you'd see as necessary, but - especially with match() - code can be made pleasantly readable ... at the cost of imposing the use of references, etc.

Upvotes: 1

pjh
pjh

Reputation: 8054

If your Perl is not ancient, you can use the first subroutine from the List::Util module (which became a core module at Perl 5.8) to do the check efficiently:

use List::Util qw{ first };

my $first_fruit = first { /\Q$fruit\E/ } @fruitArray;

if ( defined $first_fruit ) { print "I found $fruit\n"; }

Upvotes: 1

northsideknight
northsideknight

Reputation: 1557

Don't use grep, that will loop the entire array, even if it finds what you are looking for in the first index, so it is inefficient.

this will return true if it finds the substring 'apple', then return and not finish iterating through the rest of the array

#takes a reference to the array as the first parameter
sub find_apple{
    @array_input = @{$_[0]};
    foreach $fruit (@array_input){
        if (index($fruit, 'apple') != -1){
            return 1;
        }
    }
}

Upvotes: 0

MarcoS
MarcoS

Reputation: 17711

I - like @Borodin suggests, too - would simply use grep():

$fruit = 'apple';
if (grep(/^\Q$fruit\E\|/, @fruitArray)) { print "I found apple"; }

which outputs:

I found apple
  • \Q...\E converts your string into a regex pattern.
  • Looking for the | prevents finding a fruit whose name starts with the name of the fruit for which you are looking.

Simple and effective... :-)

Update: to remove elements from array:

$fruit = 'apple';
@fruitsArrayWithoutApples = grep ! /^\Q$fruit\E|/, @fruitArray;

Upvotes: 1

Borodin
Borodin

Reputation: 126722

Don't use smart matching. It never worked properly for a number of reasons and it is now marked as experimental

In this case you can use grep instead, together with an appropriate regex pattern

This program tests every element of @fruitArray to see if it starts with the letters in $fruit followed by a pipe character |. grep returns the number of elements that matched the pattern, which is a true value if at least one matched

my @fruitArray = qw/ apple|0 apple|1 pear|0 pear|0 /;

my $fruit = 'apple';

print "I found $fruit\n" if grep /^$fruit\|/, @fruitArray;

output

I found apple

Upvotes: 5

Related Questions