Re: Using IF and OR, I'm sure there is a better way
by ikegami (Patriarch) on Dec 14, 2005 at 23:37 UTC
|
And for something completely different:
# Setup
my @ok;
++$ok[$_] for 1, 2, 3;
# Sample usage
if ($ok[$variable]) {
...
}
For more flexibility, try a hash:
# Setup
my %fruit;
++$fruit{$_} for qw( apple banana orange );
# Sample usage
if ($fruit{$object}) {
...
}
These are just one step away from a dispatch table:
# Setup
my %dispatch = (
colour => \&area_fill,
scale => \&scale_image,
warp => \&warp_image,
);
# Sample usage
if ($handler = $dispatch{$command}) {
$handler->();
} else {
die("Invalid command $command\n");
}
Update: Keep in mind that 1, 2, 3 can be written as 1..3
| [reply] [d/l] [select] |
Re: Using IF and OR, I'm sure there is a better way
by cog (Parson) on Dec 14, 2005 at 23:33 UTC
|
use List::MoreUtils;
if (any { $variable == $_ } (1, 2, 3)) {
...
}
With the disadvantage of using an extra module, but with the advantage of not testing every single value after the first successful one (if the list is big, it's probably a better alternative). | [reply] [d/l] |
Re: Using IF and OR, I'm sure there is a better way
by cog (Parson) on Dec 14, 2005 at 23:29 UTC
|
if (grep { $variable == $_ } (1, 2, 3)) {
...
}
| [reply] [d/l] |
|
This unfortunately is significantly longer to execute than the boolean OR. The grep has to test every value, whereas the if statement uses short-circuit boolean logic to stop testing values as soon as a match is found.
| [reply] |
|
"significantly"? Maybe a significant factor longer, but if the OP was even considering writing it in a long || ... || ... ||, there aren't enough elements to make it significant in absolute terms.
| [reply] |
Re: Using IF and OR, I'm sure there is a better way
by GrandFather (Saint) on Dec 14, 2005 at 23:33 UTC
|
use strict;
use warnings;
my $variable = 3;
if ($variable =~ /\b(?:1|2|3)\b/)
{
print "case 1, 2 or 3\n"
}
Prints:
case 1, 2 or 3
DWIM is Perl's answer to Gödel
| [reply] [d/l] [select] |
Re: Using IF and OR, I'm sure there is a better way
by eff_i_g (Curate) on Dec 15, 2005 at 00:22 UTC
|
I use something like this:
sub in_list {
my $needle = shift || q{}; # or croak, your choice.
croak 'expecting haystack' if not @_;
return grep m/^$needle$/, @_;
}
if (in_list($var, qw(A B C))) {
...
}
| [reply] [d/l] |
|
or return grep $_ eq $needle, @_; rather.
| [reply] [d/l] |
Re: Using IF and OR, I'm sure there is a better way
by phaylon (Curate) on Dec 15, 2005 at 12:55 UTC
|
if ( any( 1, 2, 3 ) eq $n ) { ...
Ordinary morality is for ordinary people. -- Aleister Crowley
| [reply] [d/l] |
|
Hey, it looks like the Perl6 people have been reading up on Fortran 90...(although it's quite possible any was adapted to Fortran90 from some other language).
Fortran 90's any statement returns true of false if any element in an array meets a test condition, e.g.,
integer,dimension(6) :: ar
ar = (/1,3,4,5,6,7/)
if(any(ar > 4) then # returns true if any element of ar is greater tha
+n 4
call a_miracle_happens_here
endif
I'm still wondering why everybody was using regex for the test; it looks like a numerical comparison to me.
| [reply] [d/l] |
Re: Using IF and OR, I'm sure there is a better way
by Fletch (Bishop) on Dec 15, 2005 at 01:23 UTC
|
use YAML ();
$items = YAML::Load( <<EOT );
a: 1
b: 1
c: 1
EOT
if( exists $items->{ $variable } ) {
# . . .
}
| [reply] [d/l] [select] |
|
$items = {
a => 1,
b => 2,
c => 3,
};
if ( exists $items->{ $variable } ) {
# . . .
}
-Bryan | [reply] [d/l] |
|
Depends. If the list were relatively static I probably would keep it inline in the source like you've shown. If it were more dynamic or dependent on something outside the script I'd leave it external with a quick change from YAML::Load to YAML::LoadFile (granted I'd probably use a YAML sequence rather than a hash, but the idea is the same). It also could move to the bottom of the file after an __END__ marker and remain with the script but be more segregated from the flow of code.
| [reply] [d/l] [select] |
Re: Using IF and OR, I'm sure there is a better way
by davido (Cardinal) on Dec 15, 2005 at 03:00 UTC
|
List::MoreUtils' any() sub is one good way that someone mentioned. Another is a hashtable. But if the values are all contiguous, and you don't mind that floating point values could fall between '1' and '2', you could do it this way too:
if( $variable >= 1 and $variable <= 3 ) {
#...
| [reply] [d/l] [select] |
Re: Using IF and OR, I'm sure there is a better way
by swampyankee (Parson) on Dec 15, 2005 at 03:47 UTC
|
If your condition is going to be predictably in a numerical range like that, this may work.
if($variable >= $lower_limit && $variable <= $upper_limit)
{
miraculous_stuff;
}
If your requirement is to do something when $variable is an integer, vs something else when it isn't, or when $variable is being tested against values in an array, this probably would not be appropriate, but if it's a regular as what I read at 10:46pm EST 14 Dec 2005, my suggestion may be appropriate.
| [reply] [d/l] |
Re: Using IF and OR, I'm sure there is a better way
by l.frankline (Hermit) on Dec 15, 2005 at 04:09 UTC
|
Here is an another possible way...
For single numeric values:
print $& if ($variable=~/[123]/);
For two or more numeric values:
print $& if ($variable=~/[1][0]+/);
Also, take a look at perlrequick
Regards Franklin
Don't put off till tomorrow, what you can do today.
| [reply] [d/l] [select] |
|
these will work even if it is a double digit in $var (ie: 1 and 10 will both succeed for the first example) but if you only want one digit in range maybe something like:
print $& if $var =~ /^[1-3]$/;
or ... better yet ... if you are going to be doing this alot and with strings as well as digits ...
sub look_into {
my $archetype= shift;
eval 'sub { $_[0] =~ /$archetype/o; }'
}
my $is_text_am_too_red = look_into q/\b(am|too|red)\b/;
my $single_digit_in_range = look_into q/^[1-5]$/;
my $double_digit_in_set = look_into q/^[5-7][49]$/;
# etc.
if($is_text_am_too_red ->($_)){ print "get some sleep!" }
if($single_digit_in_range ->($_)){ print "single digit in range!" }
if($double_digit_in_set ->($_)){ print "double digit in set!" }
#etc.
| [reply] [d/l] [select] |
|
| [reply] [d/l] [select] |
Re: Using IF and OR, I'm sure there is a better way
by bageler (Hermit) on Dec 15, 2005 at 17:51 UTC
|
write your own shortcircuiting any() if you don't want to use cpan:
sub any {
my $var = shift;
for (@_) { return 1 if $var == $_ }
}
if (any($var,1..2000)) { print "Var is between 1 and 2000 inclusive\n"
+ }
| [reply] [d/l] |
|
Think I like this one best. I'm sure it'll bench fastest as well. Firing up the regexp engine to compare will have a noticeable overhead.
| [reply] |
Re: Using IF and OR, I'm sure there is a better way
by robin (Chaplain) on Dec 16, 2005 at 01:40 UTC
|
In Perl 5.10, you'll be able to do:
use feature '~~';
if ($variable ~~ [1,2,3]) { ... }
which will indeed short-circuit.
(I'm backporting the Perl 6 "smart match" operator to Perl 5.) | [reply] [d/l] |
Re: Using IF and OR, I'm sure there is a better way
by bravenmd (Sexton) on Dec 15, 2005 at 20:30 UTC
|
try this:
if($variable =~ /1|2|3/){
...
} | [reply] |
|
I'd recommend trying this vs seperate elsif statements on a large file and seeing if it makes a difference.
6 weeks ago I was optimising a process reading in a daily network syslog file of approx 1200 MB using 5.8.0 on an overworked Ultra 2 running Solaris 2.6.
The script had been using next if (/abc|cde|fgh|/) which *looks* most concise, but I found (to my and my workmate's surprise) that replacing it with the equivalent elsif statements made it take about 30 seconds less (it had been taking >2 minutes to read the file in).
| [reply] [d/l] |
Re: Using IF and OR, I'm sure there is a better way
by ahmad (Hermit) on Dec 15, 2005 at 20:50 UTC
|
it depends on what you're going to do after knowing if it's equal to or not , This may help
my @array = qw/1 2 3 4/;
my $matched;
foreach (@array){
if($variable == $_){
$matched = $_;}
}
it's not the best way but it may be helpful i think | [reply] [d/l] |
Re: Using IF and OR, I'm sure there is a better way
by mathy (Initiate) on Dec 16, 2005 at 16:20 UTC
|
Hey Lyle,
I figured out a way using a regular expressions comparison:
$variable=1;
if ($variable =~/[1,2,3]/)
{
print "Did it!\n";
}
I'm new in Perl, so this may be completely non-sense, but it works :)
Tell me something about this, ok?
Mathy | [reply] [d/l] |
|
| [reply] [d/l] [select] |