Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Check Array Elements

by mmittiga17 (Scribe)
on Jun 06, 2012 at 21:12 UTC ( [id://974833]=perlquestion: print w/replies, xml ) Need Help??

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

Hi All, is there a way to check the existence of multiple elements in an array? If array has 10 elements but I need to make sure 3 specific elements exist before I have script do something.

@FILES=("ABC","DEF","GHI","JKL","MNO","PQR","STU"); if ABC & GHI & MNO all exist in @FILES do something else do something else
Thanks in advance!!!!

Replies are listed 'Best First'.
Re: Check Array Elements
by toolic (Bishop) on Jun 06, 2012 at 21:18 UTC
    One way using Acme::Tools:
    use warnings; use strict; use Acme::Tools qw(intersect); my @FILES = ("ABC","DEF","GHI","JKL","MNO","PQR","STU"); if (intersect(\@FILES, [qw(ABC GHI MNO)]) == 3) { print "yes\n"; } else { print "no\n"; } __END__ yes
Re: Check Array Elements
by morgon (Priest) on Jun 06, 2012 at 21:26 UTC
    Simply use a hash (and strict!):
    use strict; my @FILES=("ABC","DEF","GHI","JKL","MNO","PQR","STU"); my %have_file = map { $_ => 1 } @FILES; if ($have_file{ABC} and $have_file{GHI} and $have_file{MNO} ) { # do something } else { # do something else }
Re: Check Array Elements
by davido (Cardinal) on Jun 06, 2012 at 22:09 UTC

    If it's just a one-time check, or if the array changes frequently, it's probably not all that efficient to suck the whole thing into a hash just to do three exists tests. Converting the big set to a hash is an O(n) operation, but a computationally more expensive one than the O(n) operation of grepping for the thee elements.

    my %find; @find{ qw( this that other ) } = (); my $found = grep { exists $find{$_} && ( delete $find{$_} || 1 ); } @b +ig_list; print "Success!\n" if $found == 3;

    This method uses a small three-element hash as the lookup list. Each time an entry is found, it is deleted from the lookup hash so that you assure that all three items are found (as opposed to the same item three times).

    If the big array changes infrequently, and you will be doing more than a few lookups on it, then it makes sense to convert the big array to a hash and invert the search:

    my %big_set; @big_set{ @big_array } = (); my @find = qw( this that other ); my $found = grep{ exists $big_set{$_} } @find; print "Success!\n" if $found == 3;

    Dave

Re: Check Array Elements
by ckj (Chaplain) on Jun 07, 2012 at 05:46 UTC
    I'll prefer this:
    @FILES=("ABC","DEF","GHI","JKL","MNO","PQR","STU"); if ((ABC~~@FILES)&&(GHI~~@FILES)&&(MNO~~@FILES)){ do something} else { do something else}
Re: Check Array Elements
by kcott (Archbishop) on Jun 07, 2012 at 00:38 UTC

    Here's a solution that allows you to change either the full (@files) or required (@need) lists of files. The order you supply the elements to either list doesn't matter: the code handles that for you. Also, filenames are likely to contain characters outside of the [A-Z] range (e.g. a.txt, b.pl, c.png, etc.): I've wrapped these in \Q...\E to avoid interference with the regex.

    use strict; use warnings; my @files = qw{ABC DEF GHI JKL MNO PQR STU}; my @need = qw{MNO ABC GHI}; my $need_re = join q{\s.*?} => map { q{\b} . qq{\Q$_\E} . q{\b} } sort + @need; if (join(q{ } => map { qq{\Q$_\E} } sort @files) =~ /$need_re/) { print qq{OK\n}; } else { print qq{NOT OK\n}; }

    -- Ken

Re: Check Array Elements
by NetWallah (Canon) on Jun 06, 2012 at 22:25 UTC
    Look Ma ! - No temp hash! (Good if you are doing this check only a small number of times).
    if ((my $x=grep {/ABC|GHI|MNO/}@FILES) == 3){ print qq|Found them all\n| }else{ print qq|found only $x\n| }
    Update Ignore the buggy version above. Revised, based on morgons (++) observations below ..
    my @need=sort qw|ABC GHI MNO|; my $flat=join "",@need; my $re="\\b" . join( "|",@need)."\\b"; if ($flat eq join( "", sort grep{m/$re/}@FILES)){ say "Found!" }

                 I hope life isn't a big joke, because I don't get it.
                       -SNL

      This is wrong.

      Counterexample:

      @FILES = ("ABC", "ABC", "ABC");
      Your grep would still report 3, event though "GHI" is missing.

      And that is even without mentioning that the regex matches also enties like "XABCY".

        Thanks for pointing out the bugs (++). Code updated above.

        I think that method is getting unwieldy. Much prefer ckjs approach below.

                     I hope life isn't a big joke, because I don't get it.
                           -SNL

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (6)
As of 2024-03-28 22:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found