Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

in_array and skipping foreach

by webchalkboard (Scribe)
on Apr 13, 2005 at 14:28 UTC ( [id://447410]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks,

Just wondering how can I check if a value exists in an array in Perl? Then if it does, just skip to the next element...

In PHP you can use in_array or something, here is how I would write it long-hand in perl, but there must be a more succinct version as there always is in Perl ;) I don't even think this version will work exactly, as I want the 'next' statement to go to the next value in the outer foreach loop, rather than the one it is in.

use Text::CSV_XS; my $csv = Text::CSV_XS->new({ 'quote_char' => '"', 'escape_char' => '"', 'sep_char' => ',', 'binary' => 1 }); open FH, "< textfile.txt" or die "Failed to open CSV file for processi +ng: $!"; my @csv=(<FH>); close(FH) or die "Failed to close CSV file for processing: $!"; my @ignore_merchants=('merchant 1','merchant 2'); foreach my $line (@csv) { if ($csv->parse($line)) { my @fields = $csv->fields; $offer{retailer}=$fields[0]; $offer{productid}=$fields[1]; foreach (@ignore_merchants) { # now I want to skip to the next element in the outer loop +. How can I do that anyway? next if ($_ eq $offer{retailer}); } }

Any ideas how I can make this better?

Cheers,
Tom

Learning without thought is labor lost; thought without learning is perilous. - Confucius
WebChalkboard.com | For the love of art...

Replies are listed 'Best First'.
Re: in_array and skipping foreach
by jdporter (Paladin) on Jan 16, 2020 at 16:34 UTC
    Any ideas how I can make this better?

    Any will do it! Specifically, the any function from the List::Util module:

    use List::Util qw( any ); next if any { $_ eq $offer{retailer} } @ignore_merchants;

    Many cases of using grep in a conditional can be written using any instead, as it can short-circuit after the first true result.

    Of course, a hash is better if you're going to be doing this check a lot of times.

    I reckon we are the only monastery ever to have a dungeon stuffed with 16,000 zombies.
Re: in_array and skipping foreach
by Joost (Canon) on Apr 13, 2005 at 14:34 UTC
Re: in_array and skipping foreach
by JediWizard (Deacon) on Apr 13, 2005 at 14:34 UTC

    First of all: You can use loop labels to controll which loop a next or last pertains to:

    OUTER: foreach my $item (@array){ foreach my $subitem (@array2){ next OUTER if($subitem eq $item); } }

    But to actually answer your question: I think it would be better to use grep in a scalar context to test for the presence of an item in an array (as opposed to foreach'ing through the array doing an eq comparison).

    foreach my $item (@array){ next if(scalar(grep({$_ eq $item} @other_array))); }

    see grep, next and last

    HTH. Cheers

    Update: As others have suggested, a hash is better for this type of lookup


    A truely compassionate attitude towards other does not change, even if they behave negatively or hurt you

    —His Holiness, The Dalai Lama

Re: in_array and skipping foreach
by Random_Walk (Prior) on Apr 13, 2005 at 14:35 UTC

    Put the ones to skip into a Hash not an array

    my %skip; $skip{$_}++ for qw(skip_me and_me and_this_too); foreach my $line (@csv) { if ($csv->parse($line)) { my @fields = $csv->fields; $offer{retailer}=$fields[0]; next if $skip{$offer{retailer}}; $offer{productid}=$fields[1]; } }

    Cheers,
    R.

    Pereant, qui ante nos nostra dixerunt!
Re: in_array and skipping foreach
by webchalkboard (Scribe) on Apr 13, 2005 at 14:42 UTC

    Doh I feel stupid, and I love hashes :) definately the way to go.

    Thanks for the info about the next labels too, I will check that out now.

    Learning without thought is labor lost; thought without learning is perilous. - Confucius
    WebChalkboard.com | For the love of art...
Re: in_array and skipping foreach
by crashulater (Initiate) on Jan 16, 2020 at 16:21 UTC

    The hints how to make an in_array() function are already in the various answers. This just puts them together

    usage: in_array($needle,@haystack)

    returns: 0 if not found and the number of instances found otherwise

    sub in_array { my $value = shift(@_) ; my @array = @_ ; return scalar(grep({$_ eq $value} @array)) ; }
Re: in_array and skipping foreach
by RazorbladeBidet (Friar) on Apr 13, 2005 at 14:31 UTC
    There's no specific function for finding a value in an array. You make your own (or use a module). Yours seems fine.

    For your second question, see next - specifically "next LABEL"
    --------------
    "But what of all those sweet words you spoke in private?"
    "Oh that's just what we call pillow talk, baby, that's all."
        Isn't it faster to create a lookuptable next to your array? The value in the array will be the key in the lookup table (hash) with the value 0 or 1.

        "We all agree on the necessity of compromise. We just can't agree on when it's necessary to compromise." - Larry Wall.
        Ah yes, I spoke to soon. Shouldn't write answers when distracted ;)
        --------------
        "But what of all those sweet words you spoke in private?"
        "Oh that's just what we call pillow talk, baby, that's all."

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://447410]
Approved by ghenry
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (4)
As of 2024-04-18 03:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found