Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

Re^2: extract only smallest numbers

by Anonymous Monk
on Jul 21, 2007 at 21:09 UTC ( #628026=note: print w/replies, xml ) Need Help??

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

    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.

      Doesn't work...
      It prints:
      jim 5 nick 29 george 12
      Thank you anyway....
        I'm skeptical of this. Can you post the exact code that produces the incorrect result?

        Well, works for me :)

        #!/usr/bin/perl while (<DATA>) { my ($name, $code) = /^(\S+)\s(\d+)/; 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}; } } for my $name (sort keys %hash) { print "$name $hash{$name}\n"; } __DATA__ jim 15 jim 522 jim 5 george 8 george 3 george 12 nick 27 nick 29


        george 3 jim 5 nick 27

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://628026]
and John Coltrane plays...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (5)
As of 2017-06-23 06:28 GMT
Find Nodes?
    Voting Booth?
    How many monitors do you use while coding?

    Results (536 votes). Check out past polls.