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

greetings all,

I am trying to go the extra mile on some classwork and make it so that my program can output processed data as a hash that is sorted by its values rather than its keys.

I am looking to end up with something like this:

Homer is 37 years old. Marge is 36 years old. Bart is 12 years old. Lisa is 9 years old. Maggie is 2 years old.

Ok, I know you can't actually sort a hash. Instead I am instead trying to pass my results into an array, use the sort function to organize the array. The goal would be to be able to use the program to sort any similar hashes. (Think %Jetsons and %Scoobydoo)

So far I have this:

#first the example %hash my %age = ( "Maggie" => 2, "Homer" => 37, "Bart" => 12, "Lisa" => 9, " +Marge" => 36); #Setting up and sorting the array... my @simpson_age = sort by_age keys %age; #I snagged this is From O'reilly's Learning Perl, 3rd ed... sub by_age { $age{$b} <=> $age{$a} }

I feel that I am close - but so far, no dice! Any tips on where to go from here?


Thanks, mox

Replies are listed 'Best First'.
Re: Sorting a hash by values...
by McDarren (Abbot) on Oct 09, 2006 at 17:34 UTC
    "Ok, I know you can't actually sort a hash.."

    Of course you can sort a hash. You can sort a hash anyway you like. What you cannot rely on however, is the unsorted ordering in a hash.

    Anyway, back to your problem at hand - all you really need to get your desired output is:

    for my $person (sort {$age{$b}<=>$age{$a}} keys %age) { print "$person is $age{$person}\n"; }

    There is really no need for the intermediate array, that is just un-necessarily complicating things.

    Cheers,
    Darren :)

      Thanks Darren! This was very helpful.

Re: Sorting a hash by values...
by chargrill (Parson) on Oct 09, 2006 at 16:28 UTC

    chinamox,

    You're extremely close. Now all you have to do is loop over @simpson_age, and use the value from that array as the key to your age hash. (Similar, but not exactly like, you're using $a and $b in your sort subroutine.)



    --chargrill
    s**lil*; $*=join'',sort split q**; s;.*;grr; &&s+(.(.)).+$2$1+; $; = qq-$_-;s,.*,ahc,;$,.=chop for split q,,,reverse;print for($,,$;,$*,$/)

      Thanks.

      With your help, I ended up with a print statment that looks closed to the one given below...

Re: Sorting a hash by values...
by johngg (Canon) on Oct 09, 2006 at 22:51 UTC
    You can also do the sorting and printing in one fell swoop using sort and map like this

    print map {qq{$_ is $age{$_} years old\n}} sort {$age{$b} <=> $age{$a}} keys %age;

    I hope this is of use.

    Cheers,

    JohnGG

    Update: Added missing closing brace in map, thanks Hue-Bond. That's what comes of hasty posting after too much beer :(

      Wow... That 'map' is sexy. I need to go read up on that more. Thanks!