http://www.perlmonks.org?node_id=795391

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

Hello All, I am trying to find the most efficient way of searching through an array for the value 0 and if it finds a zero it should break out of the search and print a Fail to the test I am running. I found out the hard way that it is not possible to do a pattern match with an array as below because it does not iterate through the elements; ... doooh !!! any suggestions?
my @results_file=(1,1,1,0,1); if (@results_file =~ m/0/) { print"\n--FAIL--"; } else { print "\n--PASS--STATUS\n"; print "\n@results_file\n"; }

Replies are listed 'Best First'.
Re: Most efficient way of search elements in an array
by Corion (Patriarch) on Sep 15, 2009 at 14:06 UTC

    So close, yet so far :)

    If you're using Perl 5.10, you can use the "Smartmatch Operator" ~~ instead of =~ and your program will work:

    use strict; for my $testcase ([1,1,1,0,1],[1,1,1,1,1],[1,10,101]) { my @results_file = @$testcase; if (@results_file ~~ m/0/) { print"\n--FAIL-- @results_file"; } else { print "\n--PASS--STATUS\n"; print "\n@results_file\n"; } }

    The only relevant change is from @results_file =~ /0/ to @results_file ~~ /0/. You might want to consider anchoring your match, so you match only a 0, and not 100, or 101.

      But Smartmatch is smart enough to match on numeric equality:
      >perl -wMstrict -le "for my $ar ( [1, 1, 0, 1], [0], [0, 0, 0], [qw(0)], [qw(00)], [qw(000)], [qw(1 1 0 1)], [1], [], [1, 10, 01, 101, 010], [qw(1 10 01 101 010)], ) { print qq{(@$ar): }, @$ar ~~ 0 ? 'naught' : 'not' } " (1 1 0 1): naught (0): naught (0 0 0): naught (0): naught (00): naught (000): naught (1 1 0 1): naught (1): not (): not (1 10 1 101 8): not (1 10 01 101 010): not
      Update: Added 'numeric string' test cases.
Re: Most efficient way of search elements in an array
by toolic (Bishop) on Sep 15, 2009 at 14:18 UTC
    Use a for loop to cycle through your array elements, and break out of the loop as soon as 0 is found using last:
    use strict; use warnings; my @results_file = (1,1,1,0,1); for (@results_file) { if (/0/) { print "\n--FAIL--\n"; last; } else { print "\n--PASS--STATUS\n"; print "\n$_\n"; } } __END__ --PASS--STATUS 1 --PASS--STATUS 1 --PASS--STATUS 1 --FAIL--

    Update: Or maybe this is the output you were looking for...

    use strict; use warnings; my @results_file = (1,1,1,0,1); my $pass = 1; for (@results_file) { if (/0/) { print "\n--FAIL--\n"; $pass = 0; last; } } if ($pass) { print "\n--PASS--STATUS\n"; print "\n@results_file\n"; } __END__ --FAIL--
      This does it alright ... except I just want one PASS to be printed if the script determines that all the array elements are 1
        Then you want my 2nd example ("Update").

        Also note that my code is equivalent to the pre-5.10 solution offered by Fletch. It wasn't obvious to me from the documentation for List::MoreUtils, until I looked at the source code for any: it does break out of the loop as soon as it finds the first match.

Re: Most efficient way of search elements in an array
by Fletch (Bishop) on Sep 15, 2009 at 14:10 UTC

    Possibly also of interest might be any from List::MoreUtils.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: Most efficient way of search elements in an array
by whakka (Hermit) on Sep 15, 2009 at 14:58 UTC
    use Test::More tests => 2; my @not_ok = (1,1,1,0,1); my @ok = (1,1,1,1,1,1); ok( not (grep { $_ == 0 } @$_), 'No zeros' ) for ( \@not_ok, \@ok );
Re: Most efficient way of search elements in an array
by Marshall (Canon) on Sep 15, 2009 at 19:49 UTC
    I don't see the need for super efficiency for an array with 5 or 10 True/False values. Use the scalar value of grep to count the number of "zeroes".
    #!/usr/bin/perl -w use strict; my @results_file=(1,1,1,0,1); print "at least one zero" if (grep{/0/}@results_file); __END__ prints: at least one zero
    numeric compare in the grep will do the same thing:
    print "at least one zero" if (grep {$_ == 0}@results_file);
    Slight modification to your code yields the following.... The grep says "tell me the number of times that '0'(zero) was seen when I looked at all elements of @results_file". Yes, there are ways to "stop counting" when the first "zero" is reached, but for just a couple of dozen things in @results_file, it just won't matter.
    #!/usr/bin/perl -w use strict; my @results_file=(1,1,1,0,1); if (grep {/0/}@results_file ) #if (grep {$_ == 0}@results_file) #numeric value { print"\n--FAIL--"; } else { print "\n--PASS--STATUS\n"; print "\n@results_file\n"; }
Re: Most efficient way of search elements in an array
by ccn (Vicar) on Sep 15, 2009 at 20:04 UTC