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

Hi monks,
my hash is below:
$r{123}{a}=3; $r{123}{b}=2; $r{456}{c}=5; $r{456}{d}=7;
I wanna get the hash's second key that is decided by
the it's max value. My ideal result is :
$r{123}{a} ==> 3
$r{456}{d} ==> 7 
how to finish it ?thx

Replies are listed 'Best First'.
Re: How to get the Max values' key!
by Anno (Deacon) on Aug 13, 2007 at 10:29 UTC
    Finish it? You haven't offered any beginning to finish.

    Here is one way:

    use List::Util qw( max); while ( my ( $first, $h) = each %r ) { my $second = { reverse %$h }->{ max values %$h}; print "\%r{$first}{$second} ==> $h->{ $second}\n"; }
    The code assumes that none of the second level hashes is empty, so the maximum always exists. If the maximum isn't unique (say if $r{123}{c} = 3 had also been given), a random key with the maximum value is selected.

    The solution is inefficient if the second level hashes are big because for each of them the full inverted hash is built just to pick out a single value.

    Anno

Re: How to get the Max values' key!
by citromatik (Curate) on Aug 13, 2007 at 10:39 UTC

    One simple way of doing this is by sorting (by value) each sub-hash:

    use strict; use warnings; my %r; $r{123}{a}=3; $r{123}{b}=2; $r{456}{c}=5; $r{456}{d}=7; for my $href (keys %r){ my $maxkey = (sort { $r{$href}->{$b} <=> $r{$href}->{$a} } keys %{$r +{$href}})[0]; print "\$r{$href}{$maxkey} ==> $r{$href}{$maxkey}\n"; }

    Outputs the desired result:

    $r{456}{d} ==> 7 $r{123}{a} ==> 3

    Hope this helps

    citromatik

Re: How to get the Max values' key!
by FunkyMonk (Bishop) on Aug 13, 2007 at 09:54 UTC
    It's not pretty, but it works

    my %r; $r{123}{a}=3; $r{123}{b}=2; $r{456}{c}=5; $r{456}{d}=7; my %new_r = map { my $max_inner; for my $inner ( keys %{$r{$_}} ) { $max_inner = $inner if !defined $max_inner || $r{$_}{$inner} > $r{$_}{$max_inn +er}; } ( $_ => { $max_inner => $r{$_}{$max_inner} } ) } keys %r; print Dumper \%new_r; __END__ $VAR1 = { '123' => { 'a' => 3 }, '456' => { 'd' => 7 } };

    If there's anything you don't understand, ask!

    update: now returns a hash, as per OP's update

Re: How to get the Max values' key!
by dogz007 (Scribe) on Aug 13, 2007 at 12:32 UTC
    Here's a one-liner that capitalizes on citromatik's sort method above:

    #!/usr/bin/perl use strict; my %r; $r{123}{a}=3; $r{123}{b}=2; $r{456}{c}=5; $r{456}{d}=7; map { print "\$r{$_->[0]}{$_->[1]} ==> $r{$_->[0]}{$_->[1]}\n" } map { [$_,(sort { $r{$_}->{$b} <=> $r{$_}->{$a} } keys %{$r{$_}})[0]]} keys %r;

    Prints:

    $r{456}{d} ==> 7 $r{123}{a} ==> 3

    UPDATE: Upon reading the question a second time, I decided that it would perhaps be more useful to maintain a hash that remembers the max valued second key for each first key, as below. The print line is just for show, since you can do anything with the hash once it is created.

    my %rmax; $rmax{$_} = (sort { $r{$_}->{$b} <=> $r{$_}->{$a} } keys %{$r{$_}})[0] for keys %r; print "\$r{$_}{$rmax{$_}} ==> $r{$_}{$rmax{$_}}\n" for keys %rmax;

    Prints:

    $r{123}{a} ==> 3 $r{456}{d} ==> 7
      I was hoping someone would use map. It's almost perfectly built for this function.
      yeah. I wanna deal with the created hash :) Thanks