http://www.perlmonks.org?node_id=628026


in reply to Re: extract only smallest numbers
in thread extract only smallest numbers

Thank you grep, but my problem is exactly on how to compare the numbers.
Assuming, for example, that I have the code:
open FILE, $my_file; while (<FILE>) { $_=~/(.*)\t(.*)/; $name=$1; $code=$2; $hash{$name} = $code; }
That is as far as I can go...

Replies are listed 'Best First'.
Re^3: extract only smallest numbers
by grep (Monsignor) on Jul 21, 2007 at 21:38 UTC
    OK.

    Couple of things first.

    • Use strict and warnings
    • Check to see if your open succeeds
    • Use split not a regex when you want to split
    • Indent your code - It makes reading the code easier on you and us
    So your code should look something like (untested):
    use strict; use warnings; open FILE, $my_file or die "Can't open $my_file\n"; my %hash; while (<FILE>) { my ($name, $code) = split(/\t/); }
    Now you have some of the problems fixed. Now you need to test what's in the hash and $code.

    One thing to remember is, that if you have not assigned a value to the hash for that key you'll get undef returned, which evaluates to 0 numerically. Since you are looking for the lowest number you'll want avoid the undef. So check the value from your hash with defined first. If you see that it is not defined, then you know to assign the value of $code whatever it is.

    # Still untested if ( !defined( $hash{$name} ) ) { $hash{$name} = $code; }
    If you have a value defined then check to see whats larger
    # Still untested if ( !defined( $hash{$name} ) or $code < $hash{$name} ) { $hash{$name} = $code; }
Re^3: extract only smallest numbers
by almut (Canon) on Jul 21, 2007 at 21:23 UTC
    ... if (!exists $hash{$name}) { # unconditionally assign the first entry $hash{$name} = $code; } else { # assign further entries only if smaller... $hash{$name} = $code if $code < $hash{$name}; }
      Yes indeed. Or more concisely, just replace your 1 line:
      $hash{$name} = $code;
      With this single line instead:
      $hash{$name} = $code if !defined $hash{$name} || $code < $hash{$name};
      ie. You assign the latest value only if it's the first value for that key name, or if it's smaller than any previous value so far.

      I'd recommend defined over exists in this case. If the hash key somehow did exist with an undefined value, the exists test would let it through, and then you'd then get a warning (under use warnings) when you got to the 'less than' comparison.

      Using defined instead will avoid this potential banana skin, and give you the correct outcome.

    A reply falls below the community's threshold of quality. You may see it by logging in.