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}

In reply to Re: Passing input through a hash then displaying results by shmem
in thread Passing input through a hash then displaying results by brayshakes

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.