Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

max key-value pair in a hash

by kettle (Beadle)
on Mar 27, 2006 at 05:23 UTC ( [id://539366]=perlquestion: print w/replies, xml ) Need Help??

kettle has asked for the wisdom of the Perl Monks concerning the following question:

Is there a better way than the following, for finding and printing the max key-value pair in a hash? I searched the site a bit and found several posts about the max value, but did not noticing anything which included printing the key:

#!/usr/bin/perl -w use strict; use warnings; my %some_hash = ( sunny => .63, cloudy => .17, rainy => .2 ); my ($max) = sort {$some_hash{$b}<=>$some_hash{$a}} keys %some_hash; print $max." :: ".$some_hash{$max}."\n"; outputs: sunny :: 0.63


I know it's debatable whether or not the 'sort' routine is optimal (or rather, it's not debatable, but depends on the size of the hash) but given that the hash is fairly small (around 60 key-value pairs) how does this size up as a solution?

Replies are listed 'Best First'.
Re: max key-value pair in a hash
by gaal (Parson) on Mar 27, 2006 at 05:36 UTC
    Yes, this is fair enough. Hashes are unordered in Perl; if you're going to need the maximal element often, or if your data grows a lot, this may become not practicable, in which case you can decide to pay the price at insertion time, and implement a tied hash that remembers its largest element instead of computing it each time you need it.

    Some people prefer an explicit subscript to a short list assignment:

    my $max = (expr)[0]; # rather than my ($max) = list_expr;

    In this case I doubt there are any performance differences, since the list must be constructed anyway.

    Update: Or, sure, you scan linearly like CountZero suggests. That's the Right Way to do this kind of thing in general (unless you go for the tied hash). But if you know your data to be this size, it probably doesn't matter much.

Re: max key-value pair in a hash
by CountZero (Bishop) on Mar 27, 2006 at 05:44 UTC
    Less cute, but (arguably) better readable and the time increases linearly with the number of records:
    use strict; use warnings; my %some_hash = ( sunny => .63, cloudy => .17, rainy => .2 ); my @key_list = keys %some_hash; my $max_key = pop @key_list; foreach (@key_list) { $max_key = $_ if $some_hash{$_} > $some_hash{$max_key}; } print $max_key." :: ".$some_hash{$max_key}."\n";

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

      For some reason, each strikes me as a slightly more natural way to do this. If nothing else, it avoids the construction of the key list.

      my %h = ( sunny => 0.063, cloudy => 0.017, rainy => 0.020, hellish => 0.103, ); my( $max_key, $max_val ) = each %h; while ( my($k,$v) = each %h ) { $v > $max_val and ($max_key,$max_val) = ($k,$v); } print "$max_key => $max_val\n";
      We're building the house of the future together.
Re: max key-value pair in a hash
by BrowserUk (Patriarch) on Mar 27, 2006 at 06:03 UTC

    #! perl -slw use strict; use List::Util qw[ max ]; my %some_hash = ( sunny => .63, cloudy => .17, rainy => .2 ); my $max = max values %some_hash; print +{ reverse %some_hash }->{ $max }, ' :: ', $max; __END__ C:\test>539366 sunny :: 0.63

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      thanks for the replies! all very helpful. I think that this last was what I was most curious about though - how to print the key, given the value. but what happens where there are two keys that share the same value? and what is the 'l' option in the shebang ??
        but what happens where there are two keys that share the same value?

        You'll get the weather associated with one of the maximal values--which one is determined by the hashing algorithm and the text of the keys.

        This is exactly the same effect as with your sort sort method.

        and what is the 'l' option in the shebang ??

        It sets $/ & $\ (INPUT and OUTPUT SEPARATORS) to \n. It just saves having to type  . "\n"; each time. One downside is that if you use a module that uses "\n" explicitly when printing stuff, it ends up double spaced, but it's useful for standalone scripts.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://539366]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (5)
As of 2024-04-23 20:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found