Reputation:
I have a nested-if code like this
if (condition1 or condition2 or condition3 ) {
if (condition1) {
}
elsif (condition2) {
}
elsif (condition3) {
}
}
Now obviously, conditions(1,2 and 3) are already checked on outer if
, so I don't want them to be checked again in inner if-elsif
statements.
So my solution was, removing the outer if
totally. But again this will make it go through if-elsif
.
So what if there are like 10-15 conditions. Which one is better? Or Is there any other better solution?
Upvotes: 1
Views: 1106
Reputation: 1482
Or this:
(condition1) ? run_statement1() :
(condition2) ? run_statement2() :
(condition3) ? run_statement3() : run_elsestatement() ;
I'm a fan of less typing. Another option, if your evaluated conditions produce 'unique' results, is to use the result as a key in a hash-of-functions. This removes the conditional checking above completely.
For instance, if the conditions were based on the value held in a scalar called '$var', then you could simply use those different values as the keys to the hash.
$conditionalFunctionHash{$var}->();
Upvotes: 0
Reputation: 46187
If your conditions are all tests on the value of the same variable, you can use given
/when
in Perl 5.10.1 and later:
use 5.010;
given ($foo) {
when ('bar') { ... } # string literal
when (4) { ... } # numeric literal
when (qw[ xyzzy plugh ]) { ... } # any of multiple literals
when (/^whee+$/) { ... } # regex match
default { ... } # fallthrough if nothing matched
}
Upvotes: 2
Reputation: 1549
Remove the outer if
statements because all the conditions will be checked anyway by the inner if
statements.
If you arrange which if
conditions according to priority as in condition1 is more important than condition2, then of course, you can't change the order of the checks.
If you arrange which if
conditions according to frequency of occurrence, then you can rearrange based on frequency, as you test or profile the program.
If condition1 is true, then run statement1. If your statements are too long, then put them into subroutines and call them, so it would look neater.
if (condition1) {&run_statement1();}
elsif (condition2) {&run_statement2();}
elsif (condition3) {&run_statement3();}
elsif (condition4) {&run_statement4();}
elsif (condition5) {&run_statement5();}
elsif (condition6) {&run_statement6();}
elsif (condition7) {&run_statement7();}
else {&run_elsestatement();}
Don't unnecessarily complicate or obfuscate the code. Keep it simple, readable and fulfilling your objectives.
Upvotes: 0
Reputation: 13792
perhaps the Switch control sentence may have sense in your code (in depends on the conditions you are checking). Take a look at the documentation of Switch.
Update Starting with the 5.10 perl release, there is a given/when control flow.
use feature "switch";
Upvotes: 1
Reputation: 57590
The outer if
is unneccessary.
Besides that, only three possible optimizations seem reasonable:
Use a data structure to represent the conditions. Should you be testing for some sort of equality (if ($foo eq $bar){...}elsif($foo eq $baz){...}
), then a hash can transform the lookup from linear to constant time:
%hash = ($bar => sub{...}, $baz => sub{...});
my $code = $hash{$foo} or do{"this is the trailing else"};
$code->(); # execute the coderef
This is wildly flexible, but includes the indirection of closures.
If you have to re-check a condition, cache the result. The scope of a variable that was declared in a condition reaches into all subsequent conditions and blocks of the if/else chain:
if ( my $cond1 = ... and ...) {
...
} elsif ($cond1 and my $cond2 = ...) {
...
} elsif ($cond2) {
...
}
Upvotes: 3
Reputation: 14728
It depends how often your code is being executed. With complicated sets of if-statements, it's better to optimise for readability, since compared to most other operations they're cheap. However, in your example above, I would remove the outer statement altogether, it's simply unnecessary. Perl optimises code while it parses it anyway.
Upvotes: 2