Re: Quicker way to do this IF statement 1-5
by demerphq (Chancellor) on May 20, 2007 at 10:53 UTC
|
my @valid= 1..5;
my %valid= map { $_=>1 } @valid;
# ...
$valid{$b} or
print "\$b has to be one of ",
join(", ",@valid[0..$#valid-1]),
" or $valid[-1]\n";
---
$world=~s/war/peace/g
| [reply] [d/l] |
|
|
The reason I like this solution the best (out of all the above, perhaps except /^[1-5]\z/) is that it's practical for values, even a large number of them, that aren't sequential.
| [reply] [d/l] |
|
|
This one gets my vote as well. Creating a hash to do the job is expressive, readable and general. Also helps you avoid hardcoding in the (1..5) values, letting you put them at the top where constants generally belong. demerphq++
| [reply] |
Re: Quicker way to do this IF statement 1-5
by varian (Chaplain) on May 20, 2007 at 08:05 UTC
|
A regex solution can be short and elegant:
if ($b=~/^[1-5]$/) {
print "\$b has to be a number and is either 1, 2, 3, 4, or 5.\n";
}
| [reply] [d/l] |
|
|
The correct regex solution :)
/^[1-5]\z/
| [reply] [d/l] |
|
|
To say that using "\z" is "the correct regex solution" (and imply that using "$" is "incorrect") is a bit silly, esp. in the absence of more detailed info regarding the application.
There are some situations where the two solutions will have different behaviors, and in such cases, it's up to the programmer to decide which is more appropriate. Either one could be more useful (or "correct") than the other, depending on the task. But in many common situations, they behave the same, and neither is "more correct" than the other.
| [reply] |
|
|
Re: Quicker way to do this IF statement 1-5
by shmem (Chancellor) on May 20, 2007 at 06:28 UTC
|
if ($b == 1 || $b == 2 || $b == 3 || $b == 4 || $b == 5) {
print "\$b is a number and is either 1, 2, 3, 4, or 5.";
} else {
print "\$b has to be a number and to be either 1, 2, 3, 4, or 5.";
}
I'd write
if ($b =~ /^\d$/ and $b > 0 and $b < 6) {
...
}
--shmem
_($_=" "x(1<<5)."?\n".q·/)Oo. G°\ /
/\_¯/(q /
---------------------------- \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
| [reply] [d/l] [select] |
|
|
if ($b =~ /^\d$/ and $b >= 1 and $b <= 5) {
...
}
DWIM is Perl's answer to Gödel
| [reply] [d/l] [select] |
Re: Quicker way to do this IF statement 1-5
by dewey (Pilgrim) on May 20, 2007 at 06:57 UTC
|
if ($b == any(1, 2, 3, 4, 5)) {
print "\$b has to be a number and is either 1, 2, 3, 4, or 5.";
}
TMTOWTDI... especially when CPAN gets into the picture!
Update: After rereading the thread and the rest of the replies... maybe the method I gave here is best considered as a curiosity or demonstration of this module's abilities, rather than as a practical solution. Just don't forget about it when you need to solve a more general version of the problem.
| [reply] [d/l] |
Re: Quicker way to do this IF statement 1-5
by syphilis (Archbishop) on May 20, 2007 at 06:52 UTC
|
First up note that the condition (as stated) is satisfied for some values of $b that are not digits in the range 1 to 5. For example the numbers 2.0, 3e0, 4.0e0, and the string '5anything' will all satisfy the condition. If you really want to ensure that $b is a single digit in the range 1 to 5, then I think the following may suffice -given that the value comes from a form, and is therefore presumably being assigned to $b as a string, not a number:
if (length($b)== 1 && $b >= 1 && $b <= 5) {
print "\$b has to be a number and is either 1, 2, 3, 4, or 5.";
}
But if $b were to be assigned the number 4.0e0, rather than the string '4.0e0', you would find it still satisifed the condition (as rewritten by me).
On the other hand, if all you want to do is use the numeric value of whatever it is that the user supplied, then I can't really think of any improvement you could make on your original if() statement.
Cheers, Rob Update: Replaced length($b == 1) with length($b) == 1 ... smart move, methinks :-)
| [reply] [d/l] [select] |
Re: Quicker way to do this IF statement 1-5
by naikonta (Curate) on May 20, 2007 at 14:32 UTC
|
no warnings qw(uninitialized numeric);
print "\$x is a number ($x) is either 1, 2, 3, 4, or 5.\n"
if grep {$x == $_} (1 .. 5);
Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!
| [reply] [d/l] |
Re: Quicker way to do this IF statement 1-5
by zer (Deacon) on May 20, 2007 at 06:25 UTC
|
print "\$b has to be a number and is either 1, 2, 3, 4, or 5." if ($b
+< 1 || $b > 5);
That is one method
Take a look at perlintro. It has good explenations of all the constructs | [reply] [d/l] |
Re: Quicker way to do this IF statement 1-5
by ww (Archbishop) on May 20, 2007 at 13:28 UTC
|
Aside: using variable names like $(one letter) can make life difficult for you (later) or future maintainers. The stock suggestion, "use meaningful variable names," is a cliche for good reason!
...and specifically re $a and $b -- those are conventionally used ONLY by and for sort. See the examples in perldoc -f sort.
| [reply] [d/l] |
Re: Quicker way to do this IF statement 1-5
by swampyankee (Parson) on May 21, 2007 at 11:56 UTC
|
Since an input validation is not likely to be a big user of system resources, an "optimal" solution is one that's easy to read and easy to change.
If the value is being used for something which could be character-based, such as a menu selection, use a hash, as suggested by demerphq. If it's going to be used for something that will be strictly numeric, I would just do something like this:
use strict;
use warnings;
my $entered_value;
my $min_allowed = 1;
my $max_allowed = 5;
if($entered_value =~ /^\d+\z/s and
($entered_value >= $min_allowed and $entered_value <= $max_allowed)
+)
{
do_magical_processing($entered_value);
}
else{
print "value must be a number no less than $min_value and not grea
+ter than $max_value\n";
}
And a grammatical quibble: "either" should only be used when there are exactly two choices.
emc
Insisting on perfect safety is for people who don't have the balls to live in the real world.
—Mary Shafer, NASA Dryden Flight Research Center
| [reply] [d/l] |
Re: Quicker way to do this IF statement 1-5
by zer (Deacon) on May 20, 2007 at 20:06 UTC
|
If he is looking for the quicker way. Would a regex really be the best solution? | [reply] |
|
|
If he is looking for the quicker way. Would a regex really be the best solution?
If he's looking for the quickest way to that thing, then he's most probably micro-optimizing, which is most probably not good. But AIUI he's rather searching for a slightly less clumsy solution than his own.
| [reply] |
Re: Quicker way to do this IF statement 1-5
by PerlPhi (Sexton) on May 20, 2007 at 06:57 UTC
|
for (1..5) {
$_ == $b ? goto JUMP : 0;
}
print "\$b has to be a number and is either 1, 2, 3, 4, or 5.";
JUMP:
just another way around... just choose the best (comfortable) for you.
| [reply] [d/l] |
|
|
for (1..5) {
$_ == $b ? goto JUMP : 0;
}
print "\$b has to be a number and is either 1, 2, 3, 4, or 5.";
JUMP:
Please do not make me repent of having mentioned goto to you!!
Also, I'm fully aware of your obsession for ?: (in fact I even frontpaged that other thread, since after all a nice discussion got out of it) but then again there's no need to use it there: it's plain ugly. Do you really want to stay concise? Just use a short circuiting and:
$_ == $b and goto JUMP for 1..5;
But really: do not use goto at all, and adopt some of the other solutions others suggested, instead.
using goto won't hurt you when you just use it once... and the distance of goto and the refering label name should be as much as possible close to each other so you can keep an eye on that.
Using goto will hurt you even when you just use it once... because then you will want to use it twice, then three times and so on. And first or later you will want to insert some code between a goto and its target, because "that's not much code". And then some more, because that's still not too much", and so on. And first or later it will bite you back in the neck. And even without that, quite a lot of programmers will think you're an asshole anyway. Of course you can live with that, but... I wouldn't: there's a good reason why they would. | [reply] [d/l] [select] |
A reply falls below the community's threshold of quality. You may see it by logging in.
|