Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?

sorting hash of hashes

by tevads (Initiate)
on Apr 24, 2001 at 18:27 UTC ( #75058=perlquestion: print w/replies, xml ) Need Help??

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

I have created a multi level hash : $pnl_ind{$symbol_set}->{$symbol}->{'pnl'} I want to sort 1st by $symbol_set then by 'pnl' then by $symbol. I have tried this:
foreach my $symbol_set (sort keys %pnl_ind) { my $symbols_r=$pnl_ind{$symbol_set); foreach my $symbol (sort ($a->{'pnl'}<=>$b->{'pnl'})%$symbols_r ) +{ ... etc
This only sorts by symbol_set and not by 'pnl'. Anybody have any ideas or who could provide code to solve this. Thanks tevads

Replies are listed 'Best First'.
Re: sorting hash of hashes
by suaveant (Parson) on Apr 24, 2001 at 18:38 UTC
    well... you do a foreach of %pnl_ind, which gives you the sorted keys into the hash at the $symbol key level, which you put in $symbols_r... you then sort the HASH at that level, not the keys... that is one problem. Another problem is that you are trying to sort the values of the 'pnl' keys, but $symbols_r's keys are the $symbol keys, one level back from the 'pnl' keys...

    Are you trying to do the following?

    foreach my $symbol_set (sort keys %pnl_ind) { my $symbols_r=$pnl_ind{$symbol_set); foreach my $symbol (sort ($symbols_r->{$a}{'pnl'}<=>$symbols_r-> +{$b}{'pnl'}) keys %{$symbols_r} ) { ... etc
    That should sort by symbol set, then return the symbol key sorted on the value of the 'pnl' hash entry inside it. Let me know if you need furthur clarification of bits of it.
                    - Ant
      Thank you very much for your help on this. Your solution worked perfectly. tevads
        excellent, glad to help... do you see everything that is going on there?
                        - Ant
      ++ for you for that answer. I have a question...

      I thought I was in the twilight zone earlier when I came to perlmonks to put down a question about sorting multidimensional hashes and the top question here was just that!

      here's mine...
      I have a 4 dimensional hash something like this: $logdata->{$log}->{$line}->{$category} = $value and I need to sort at the $log level by the value of a particular $category.
      I already know what categories I need to sort by but don't want to write different subs for each.
      My attempt went something like...

      for my $log ( sort { if (!$query->param('merge')) { $a cmp $b } else { # it's merged so we have to sort at +log level rather than line level if ($query->param('sortby') eq 'time_as +c') { for my $line ( keys %{$logdata->{$l +og}} ) { my $timeA = $logdata->{$a}->{$l +ine}->{'time'}; my $timeB = $logdata->{$b}->{$l +ine}->{'time'}; $timeA cmp $timeB; } } elsif ($query->param('sortby') eq 'time +_des') { for my $line ( keys %{$logdata->{$l +og}} ) { my $timeA = $logdata->{$a}->{$l +ine}->{'time'}; my $timeB = $logdata->{$b}->{$l +ine}->{'time'}; $timeB cmp $timeA; } } } } keys %$logdata ) { my $loglines = $logdata->{$log}; for my $line ( sort keys %$loglines ) {

      but since I am all "use strict;"-ed up, Perl moans that $log needs an explicit package name for $log in the for my $line ( keys %{$logdata->{$log}} ) { lines. This is more complicated than anything I have had to do to date and this is where I got stuck.

      Against my better judgement I tried a foreach my $log (keys %$logdata) { above the two lines mentioned in the last paragraph but the output was not quite what I was looking for (a bunch of empty lines inamongst the UNsorted output).

      I have a solution - make the first key in %$logdata "$log|$line" and remove a level from the hash but I figure there has to be a way to do this properly. Any help would be much appreciated.


        Ok, first of all... you should put a sort that large in a subroutine, just for simplicity's sake...
        for(sort sort_sub @foo) ... sub sort_sub { $a <=> $b; }
        Similar to that... make your code MUCH more readable :)

        Perl moans about $log not being there because it isn't... $log isn't filled until after the sort is done... your $log data is in $a and $b.

        So, let me get this straight... you want to sort at the first level of your hash, by a key in the 3rd level of your hash? The problem I see in this is... I assume you have many lines (i.e. $line data)? If that is true, then how do you find the category you need under many lines? Or is there just one line that has a 'time' category, and that is the one you need?

        Can you give a small example of what your hash looks like?
                        - Ant

Re: sorting hash of hashes
by mrmick (Curate) on Apr 24, 2001 at 18:31 UTC

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (3)
As of 2021-11-27 09:08 GMT
Find Nodes?
    Voting Booth?

    No recent polls found