As always, there is more than one way to do it. Please see code below for some illustrations. Some comments:
- Using @zeros in the sub is a bad idea. All numbers to be tested should be passed as arguments, see below. I had not mentioned this.
- "int" only cuts of digits. So int(2.9999) is 2 which is not what you want. One can use it for rounding, but it is more complex and there is a module doing it for us: Math::Round.
- I have illustrated the use of our test function with a few examples below.
- In grep you can iterate either over your keys or over the arrays, you just need to call the test function appropriately.
- As you are iterating over all elements of the hash, speed of lookup is not an issue in my opinion.
Hope this helps.
use strict;
use warnings;
use Math::Round qw/round/;
use Data::Dumper;
# function returns 1 if all arguments are integer
# zero otherwise
sub is_approximately_an_integer {
my $eps = 0.0001;
while( my $x = shift ) {
# need to use "round", "int" does not work!
return 0 if abs( $x-round($x) ) > $eps;
}
return 1
}
# some test cases
print "Testing...\n";
print is_approximately_an_integer( 1, 3.99999999, 5 ), "\n";
print is_approximately_an_integer( 1.2, 3.99999999, 5 ), "\n";
print is_approximately_an_integer( 1, 3.99999999, 5.0000001 ), "\n";
print is_approximately_an_integer( 1, 3.99999999, -5 ), "\n";
print is_approximately_an_integer( 1, 3.99999999, -5.1 ), "\n";
print is_approximately_an_integer( 1, 3.99999999, -5.000000001 ), "\n"
+;
print is_approximately_an_integer( 1, -3.99999999, -5.000000001 ), "\n
+";
print is_approximately_an_integer( 1 ), "\n";
print is_approximately_an_integer( 1.5 ), "\n";
# what if we have hash of arrays ?
my %hash = (
"1,2,3" => [ 1, 3.99999999, 5 ],
"1,2,4" => [ 1.2, 3.99999999, 5 ],
"1,2,5" => [ 1, 3.99999999, 5.0000001 ],
# etc
);
# this returns only the arrays but lose keys
print "\nSelected arrays\n";
my @wants = grep { is_approximately_an_integer( @$_ ) } values %hash;
print Dumper( @wants );
# this returns the keys
print "\nSelected keys...\n";
my @wants = grep { is_approximately_an_integer( @{$hash{$_}} ) } keys
+%hash;
print Dumper( @wants );
print "...and the associated array.\n";
# and you can get the arrays as well
print Dumper( @hash{@wants} );
|