Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

How to Do Multiple OR in For Loops

by neversaint (Deacon)
on Apr 13, 2011 at 01:30 UTC ( #899073=perlquestion: print w/ replies, xml ) Need Help??
neversaint has asked for the wisdom of the Perl Monks concerning the following question:

Dear Masters,
I have a hard-coded if loops that looks like this:
my $tp = 0; my $fp = 0; if ( $myhash{$pred} || $myhash{$pred1} || $myhash{$pred2} || $myhash{$pred3} || $myhash{$pred4} || $myhash{$pred5} || $myhash{$pred6} ) { $tp++; } else { $fp++; }
How can I do that in for loops? I tried the following but it give different result:
my $tp=0; my $fp=0; my @allpreds = ($pred,$pred1,$pred2,$pred3,$pred4,$pred5); foreach my $allpred ( @allpreds ) { if ( $myhash{$allpred} ) { $tp++; } } if ( !myhash{$pred} ) { $fp++; }


---
neversaint and everlastingly indebted.......

Comment on How to Do Multiple OR in For Loops
Select or Download Code
Re: How to Do Multiple OR in For Loops
by Anonymous Monk on Apr 13, 2011 at 01:38 UTC
    my $tp=0; my $fp=0; my @allpreds = ($pred,$pred1,$pred2,$pred3,$pred4,$pred5); foreach my $allpred ( @allpreds ) { if ( $myhash{$allpred} ) { $tp++; } } if ( !myhash{$pred} ) { $fp++; } __END__ Can't call method "myhash" on an undefined value at - line 13.
Re: How to Do Multiple OR in For Loops
by Anonymous Monk on Apr 13, 2011 at 01:41 UTC
    if ( grep { exists $myhash{ $_ } } @pred ){ $tp++; } else { $fp++; }
Re: How to Do Multiple OR in For Loops
by davido (Archbishop) on Apr 13, 2011 at 01:44 UTC

    Try this:

    my $tp = 0; my $fp = 0; for( $pred, $pred1, $pred2, $pred3, $pred4, $pred5, $pred6 ) { if( $myhash{$_} ) { $tp++; } else { $fp++; } }

    You might consider avoiding all those variable names with numbers. Just drop the values into an array called @pred in the first place. Then it would look like:

    for( @pred ) { .........

    Dave

Re: How to Do Multiple OR in For Loops
by toolic (Chancellor) on Apr 13, 2011 at 01:44 UTC
    Untested:
    my $tp = 0; my @allpreds = ($pred,$pred1,$pred2,$pred3,$pred4,$pred5,$pred6); foreach my $allpred ( @allpreds ) { if ( $myhash{$allpred} ) { $tp = 1; last; } } my $fp = ($tp == 1) ? 0 : 1;
        !!!$tp is the same as just !$tp, and it's not equivalent to $tp ? 0 : 1.
        $ perl -E'$tp=1; say "[", !$tp, "]";' [] $ perl -E'$tp=1; say "[", $tp ? 0 : 1, "]";' [0]
Re: How to Do Multiple OR in For Loops
by ikegami (Pope) on Apr 13, 2011 at 01:54 UTC
    I'd go for
    my $tp = grep { $myhash{ $_ } } @pred;

    If the boolean needs to be formatted into '0' and '1' for output, that's the output code's job, and it can be done there trivially using « ? '1' : '0' ».

    Using "for", it would look like

    my $tp = 0; for ( @pred ) { if ( $myhash{ $_ } ) { $tp = 1; last; } }
    or
    my $tp = 0; for ( @pred ) { last if $tp = $myhash{ $_ }; }
Re: How to Do Multiple OR in For Loops
by LanX (Canon) on Apr 13, 2011 at 02:16 UTC
    List::Util is core, try importing reduce();

    untested:  if ( reduce { $a||$b } @myhash{@allpreds} ) {...}

    Cheers Rolf

    UPDATED: tested and works!

    If you dont like the hashslice you can also use  map {$myhash{$_}} @allpreds instead.

Re: How to Do Multiple OR in For Loops
by JavaFan (Canon) on Apr 13, 2011 at 06:40 UTC
    my $tp=0; my $fp=0; my @allpreds = ($pred,$pred1,$pred2,$pred3,$pred4,$pred5); $fp++; foreach my $allpred (@allpreds) { if ($myhash{$allpred}) { $tp++; $fp--; last; } }
Re: How to Do Multiple OR in For Loops
by Marshall (Prior) on Apr 13, 2011 at 09:17 UTC
    Your "if" statement is very efficient. There is no need to change it unless you need to make a major expansion of the $predX variables, probably with a @pred array. Otherwise, I see no need to re-visit and change working code.

    Do not mistake fewer lines of code for greater efficiency.
    However, ikegami's code looks to me to be short, efficient and uses the power of the language, ie. grep.

      Note though that || short circuits (doesn't evaluate more clauses than needed to calculate the answer), where as grep will always perform all checks.

      Of course, it's not very common to have so many clauses that it matters. You may need hundreds, if not thousands of clauses to make a significant difference (and then only if there's a true clause "early" enough).

        I was wondering if the short circuit could cause side effects. But in this case there is no risk of auto-vivication.

        With side-effects I'd rather prefer a non short circuit solution for clarity.

        If a short circuit effect is side effects areš wanted, it should be done explicitly.

        Cheers Rolf

        1) corrected bad phrasing!

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (11)
As of 2014-07-14 11:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    When choosing user names for websites, I prefer to use:








    Results (257 votes), past polls