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

Hi all , Need help.How to sort the values of the below HOH.

***************************************************
$data{1} = {'a' => 10, 'b' => 5, 'c' => 20 };
$data{2} = {'a' => 90, 'b' => 15, 'c' => 40 };
***************************************************

I would like to take top 3 values from the both hashes.
Required Outout
---------------
$data{1}{b}
$data{1}{a}
$data{2}{b}

thanks,
swaroop

Replies are listed 'Best First'.
Re: Sorting HOH
by tlm (Prior) on May 02, 2005 at 15:46 UTC
    use strict; use warnings; my %data = ( 1 => { a => 10, b => 5, c => 20 }, 2 => { a => 90, b => 15, c => 40 } ); my @top_3 = ( sort { $a->[-1] <=> $b->[-1] } map { my $k = $_; my $h = $data{ $_ }; map [ $k, $_, $h->{$_} ], keys %$h } keys %data )[ 0..2 ]; for ( @top_3 ) { printf "\$data{%d}{%s} = %d\n", $_->[0], $_->[1], $data{$_->[0]}{$_->[1]}; } __END__ $data{1}{b} = 5 $data{1}{a} = 10 $data{2}{b} = 15

    the lowliest monk

Re: Sorting HOH
by ihb (Deacon) on May 02, 2005 at 15:18 UTC

    As ysth says your question is a bit vague. Anyway, here's an approach that you can start to work with.

    use Hash::Flatten qw/ flatten unflatten /; sub pair { ... } # 1,2,3,4 => [1,2],[3,4] my %data; $data{1} = {'a' => 10, 'b' => 5, 'c' => 20 }; $data{2} = {'a' => 90, 'b' => 15, 'c' => 40 }; my @sorted = sort { $a->[1] <=> $b->[1] } pair(%{flatten(\%data)}); print $_->[0], "\n" for @sorted[0..2]; __END__ 1.b 1.a 2.b
    You'll have to implement &pair yourself.

    ihb

    See perltoc if you don't know which perldoc to read!

Re: Sorting HOH
by ysth (Canon) on May 02, 2005 at 15:11 UTC
    Are you wanting your HOH to be modified? Or just to output all but the highest three values? Is your required output actually the literal text '$data{1}{b}', etc., or 5, 10, 15?

    Update: I see other's interpreted "top" as meaning lowest; I was somehow stuck on having "top" mean highest, and had to somewhat unnaturally interpret "take" as "exclude" :)

Re: Sorting HOH
by mda2 (Hermit) on May 02, 2005 at 17:14 UTC
    Updated Code mistake cuted... (my first update :) ) If you need only top values it's one more option:
    $data{1} = {'a' => 10, 'b' => 5, 'c' => 20 }; $data{2} = {'a' => 90, 'b' => 15, 'c' => 40 }; @Top = sort { $a <=> $b } map { # cut values %{$data{$_}} } keys %data; @Top[0..2]; # or simplify to ( sort { $a <=> $b } map { # cut values %{$data{$_}} } keys %data; )[0..2];

    --
    Marco Antonio
    Rio-PM

      Why are you doing two sorts or looking at keys? All you work with is the values of the values:
      my @Top = sort { $a <=> $b } map { values %{$_} } values %data;

      Caution: Contents may have been coded under pressure.
        Thanks. But I need the key values too. Anyways , got the solution.

        Thanks again,
        Swaroop