Close, yes, for some value of close ;-) Move the comparison into a loop.
Conditionals as keys to a hash don't work. Hash keys are strings. Ok, you have your conditions inside double quotes, and $grade is defined (but you should chomp it, since it contains a trailing newline), so you end up with a string that could be evaluated with eval. But what if "wibble" was entered? You would end up having
%scores = (
"wibble<=90" => "A",
...
);
which isn't a valid comparison. You need to check the content of $grade first.
It seems from your code that you want to have the comparisons evaluated in the
order they are listed. You can't operate directly on a hash for that without bringing the keys into order, since a hash's elements aren't necessarily (in fact, unlikely) returned in the order they were entered.
$grade = <STDIN>;
...
foreach $grade (%scores) {
Here you are masking the $grade variable with a temporary loop variable. No way to get at what you've read from STDIN. And you are iterating over a flat list of key/value pairs.
If you want to iterate over the keys of your hash, use
foreach my $key (keys %hash) {
...
}
To iterate over the values, use
foreach my $value (values %hash) {
...
}
One approach for your problem is reversing your hash and using anonymous subroutines as values:
chomp (my $grade = <STDIN>);
$grade !~ /^\d+$/ and die "Input must be numeric!\n";
my %scores = (
A => sub { return $_[0] <= 90 ? 1 : 0 },
B => sub { return $_[0] <= 80 ? 1 : 0 },
C => sub { return $_[0] <= 70 ? 1 : 0 },
D => sub { return $_[0] <= 60 ? 1 : 0 }, # just a guess, otherwise
+ like 'B'
F => sub { return $_[0] >= 50 ? 1 : 0 }, # really? shouldn't that
+be '<=' ?
);
my $result;
foreach my $key (qw(D C B A F)) {
if ($scores{$key}->($grade) ) {
$result = $key;
last;
}
}
print $result,$/;
Note that 'F' is never returned, since for all $grade <= 60 'D' will be returned. If you evaluate 'F' up front, none of A - D will ever be returned.
So maybe you have a typo, and you really mean your comparisons to be identical for all keys? That would simplify things, no need for anonymous subs, no need to reverse the hash:
chomp (my $grade = <STDIN>);
$grade !~ /^\d+$/ and die "Input must be numeric!\n";
# hash with upper threshold as keys
my %scores = (
90 => 'A',
80 => 'B',
70 => 'C',
60 => 'D',
50 => 'F',
);
my $result;
foreach my $key (sort keys %scores) {
if ($grade <= $key) {
$result = $scores{$key};
last;
}
}
print $result, $/;
--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}
|