note: this is first attempt at a string reg exp in real time. the regexp didnt act exactly as imagined but the tested regexp is at the bottom of the post now.
Thinking in terms of the keys being strings and not being floating point numbers I went for a regexp match. This assumes only one decimal precedes the first decimal point at the start of the pattern (key) and each of the rest are 3 digits.
foreach my $nums (keys %hash){
if($hash{$nums}
=~
m/^([^0]|((0\.[5-9]\d{2})|(0\.4[([^0]{2})([^0]\d)(\d[^0])])))/){
print "$nums is linked with url $hash{$nums}\n";
# or do something with $hash{$nums}
}
}
Don
(revision #401,0*!)
Sleepless Addendum: On reflection the first group of [^0] after the test for the '4' are not required. The two (not three) groups there should be \d[^0] and [^0]\d in that order. These test for all options aside from the double zero of the 400 which is what I was over securing for. so not
(0\.4[([^0]{2})([^0]\d)(\d[^0])])
as this tests for '00' first which is least likely, then goes on to test for all double digit numbers failing at 00 01 02 .. 09. then tests for the second 0 again to see if it is 00 or allowable.
but
(0\.4[(\d[^0])([^0]\d)])
This just carries out the test for any double digit failing at 00 10 20 .. 90, allowing say 07, then fails on the second test only if the first 0 is there meaning it is 00 and not say 20.
I also quickly considered testing for any number that was not higher than 0.4 but this resulted in over matching required when reaching the 400 again, or i had actually fallen asleep by then. lol.
re note: ok so I actually decided to test it out on a hash literal specifically designed with fails. plusplus if you already guessed :p - the first ^0 matched and that concluded the test so basically it wasnt testing for 01..09. However this is the way to go about that one. And of course should always test before responding to a seeker of wisdom, my bad.
use strict;
use warnings;
my %numsh = (
'0.000' => "noughtpointnought",
'0.004' => "noughtpointohohfour",
'0.040' => "noughtpointohfouroh",
'0.123' => "noughtpointonetwothree",
'0.399' => "noughtpointthreeninenine",
'0.400' => "noughtpointfourohoh",
'0.405' => "noughtpointfourohfive",
'0.410' => "noughtpointfouroneoh",
'0.411' => "noughtpointfouroneone",
'0.490' => "noughtpointfournineoh",
'0.500' => "noughtpointfiveohoh",
'0.904' => "noughtpointnineohfour",
'1.123' => "onepointonetwothree",
'4.000' => "fourpointhohoho",
'4.050' => "furpintohfiveoh",
'4.400' => "fourpointfourohoh",
'4.405' => "fourpointfourohfive",
'4.410' => "fourhtpointfouroneoh",
'4.411' => "fourpointfouroneone",
'4.490' => "fourpointfournineoh",
'5.050' => "fivepointohfiveoh",
'7.050' => "sevenpointohfiveoh",
'0goodword' => 'nogoodword',
);
#print scalar(%numsh).$/;
foreach my $num (sort keys %numsh){
if ($num =~ m/^([^0]|(0\.([5..9]|4([^0]|(0[^0])))))/){
print "$num is $numsh{$num}".$/;
}
}
exit(0);
so you have to explicitly 'or' match, a non zero character first followed by the 'or' zero followed by non-zero. Which funnily enough is a recursion of the start of the regex itself....
and for added measure the lower than regexp seems to work like this:
if ($num =~ m/^(0\.([0-3]|400))/){
print "$num is $numsh{$num}".$/;
}
note the different range operators '5..9' in the first and '0-3' in the second. strange huh.
Don |