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

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

Hello monks,
lets say you have an array:
@array=(34,52,67,3,66);

and you want to check if at least one element is bigger than 10.
Is there a way to do it in a loop, like:
foreach $i(@array) { ?????????????????????? }

and print the success message only once? I mean, I want to print something like :"Yes, at least one is bigger than 10", but not print it 4 times (since 4 of my numbers are bigger than 10.
It must be something silly that I can't think about, but I'm new to Perl and don't know much yet...

Replies are listed 'Best First'.
Re: Check if at least one element of array is bigger than X
by GrandFather (Saint) on Apr 08, 2010 at 00:33 UTC

    The conventional Perl tool for finding stuff in arrays is grep. Consider:

    if (grep {$_ > 10} @array) { print "Yes, at least one is bigger than 10\n"; }

    In this case grep returns a list containing all the elements that match the > 10 test. In a scalar context (which is the case for an if expression) the number of elements in the list is given so the test is really "are there any elements who's value is > 10?". grep implies the loop btw, but wraps it up in a pretty package.

    True laziness is hard work
      <O>so the test is really "are there any elements who's value is > 10?"

      Maybe logically, but it still checks the entire list.

        but it still checks the entire list

        So what? Maybe that is an issue if the list is tens of thousands of items long and the test is being performed often, but in most cases neither criteria is met and the simplistic grep solution is by far the simplest and most maintainable technique. For the vast majority of cases avoiding grep for efficiency reasons is a perfect example of why we implore people to avoid premature optimisation.

        When I was writing my original reply I considered opening that particular can of worms, but given the nature of the OP's question decided that the additional layer of confusion wasn't warranted - sigh.

        True laziness is hard work
Re: Check if at least one element of array is bigger than X
by toolic (Bishop) on Apr 08, 2010 at 00:09 UTC
    The List::MoreUtils::any function was designed to do such a thing:
    use strict; use warnings; use List::MoreUtils qw(any); my @array = (34,52,67,3,66); print "At least one value > 10" if any { $_ > 10 } @array; __END__ At least one value > 10
    any is efficient in the sense that the function will return as soon as the condition is met; it will not loop through the entire array if it does not have to. This is similar to the last solution above.
Re: Check if at least one element of array is bigger than X
by repellent (Priest) on Apr 08, 2010 at 02:45 UTC
    List::Util is a core module.
    use List::Util qw(first); my $got_big = first { $_ > 10 } (34,52,67,3,66);
Re: Check if at least one element of array is bigger than X
by Anonymous Monk on Apr 07, 2010 at 23:43 UTC
Re: Check if at least one element of array is bigger than X
by ambrus (Abbot) on Apr 08, 2010 at 08:51 UTC

    Forgive me if I'm traditional, but we had none of these problems when we used real for loops or while loops instead of these fancy new control structures.

    for (my($i, $quit) = 0; !$quit && $i < @array; $i++) { if (10 < $array[$i]) { print "array element at index $i value $array[$i] is bigger th +an 10\n"; $quit++; } }

    This is part joke, part serious.

Re: Check if at least one element of array is bigger than X
by Marshall (Canon) on Apr 08, 2010 at 09:39 UTC
    I like Grandfather's solution. It uses the scalar value of grep in an "if" statement and the simplicity of this is normally the best way to go. If @array is very big, here is one way to stop processing once you have a "match". This speeds things up at the cost of complexity.
    #!usr/bin/perl -w use strict; my @array=(34,52,67,3,66); is_value_gt_min_array_element(5,\@array) ? print "yes, 5 is greater than @array\n" : print "no, 5 isn't greater than: @array\n"; is_value_gt_min_array_element(3,\@array) ? print "yes, 3 is greater than @array\n" : print "no, 3 isn't greater than: @array\n"; is_value_gt_min_array_element(2,\@array) ? print "yes, 2 is greater than @array\n" : print "no, 2 isn't greater than: @array\n"; sub is_value_gt_min_array_element { my ($value, $arrayref) = @_; foreach (@$arrayref) { return 1 if ($value > $_); #this is a "found it!" #stop searching for another one } return 0; } print "There are ", scalar(grep{$_>3}@array), " numbers ", "greater than 3 in: @array\n"; __END__ prints: yes, 5 is greater than 34 52 67 3 66 no, 3 isn't greater than: 34 52 67 3 66 no, 2 isn't greater than: 34 52 67 3 66 There are 4 numbers greater than 3 in: 34 52 67 3 66
Re: Check if at least one element of array is bigger than X
by nvivek (Vicar) on Apr 08, 2010 at 05:16 UTC
    You try this,
    use strict; use warnings; my @array=(34,52,67,3,66); my $temp; map { $temp=$_ if $_ > 10 } @array; print "Yes,at least one number is bigger than 10\n" if($temp);
    The above map operation will check any element of the array and store it to temp if it is greater than 10. Finally,we will check whether the temp is containing value or not.If it isn't undef,printing the message as greater than 10 in an array. If you don't want to store any temporary variable,then you try this.
    use strict; use warnings; my @array=(34,52,67,3,66); map { print "Yes,at least one number is bigger than 10\n" and exit if +$_ > 10 } @array;
      I must agree with GrandFather. This is the grep solution gone horribly wrong.

      How is either solution better than any of the other solutions that have been provided?

      True laziness is hard work
Re: Check if at least one element of array is bigger than X
by syphilis (Archbishop) on Apr 08, 2010 at 06:44 UTC
    but not print it 4 times

    The other solutions are better, but you could just print the message the first time only (untested):
    my $mess = 1; foreach $i(@array) { if($i > 10) { print "Bigger than 10" if $mess; $mess = 0; } } $mess = 1; # In case we want to use it again.
    This would allow you to (if needed) iterate through the whole loop, but display the message only once.

    Cheers,
    Rob

      More than one way to skin a cat:

      #!/usr/bin/perl use strict; use warnings; my @array = (1..10); my $found = 0; for (@array) { $found ++ if $_ > 10; } print "Bigger than 10" if $found;

      ___________
      Eric Hodges
Re: Check if at least one element of array is bigger than X
by Anonymous Monk on Apr 08, 2010 at 17:50 UTC
    @array=(34,52,67,3,66); checkarray(\@array); sub checkarray(){ my $arref = shift; foreach my $entry (@{$arref}){ if( $entry > 10 ){ print "yes one is bigger than 10"; return 1; }; } return 0; }; # sub