Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Re: sorting hash of hashes

by suaveant (Parson)
on Apr 24, 2001 at 18:38 UTC ( [id://75065]=note: print w/replies, xml ) Need Help??


in reply to sorting hash of hashes

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

Replies are listed 'Best First'.
Re: Re: sorting hash of hashes
by Anonymous Monk on Apr 24, 2001 at 19:21 UTC
    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
        Not sure if the original poster understood, but I'm still a little lost, could you go into more detail?

        Kickstart

Re: Re: sorting hash of hashes
by larryk (Friar) on Apr 25, 2001 at 14:54 UTC
    ++ 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.

    larryk

      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

        I agree it _would_ make it more readable and I tried to put it in a sub but the sort option (8 to be precise) comes from $query-param('sortby') (CGI.pm) which, as far as I can tell by failed attempts, I cannot pass thusly: (while using sic strict)
        foreach my $x (sort sortsub($query) keys %y) {...

        Every line has a time on it and I have to sort a number of logs by like times of day. Data is as follows:

        log1.log<br> --------<br> Time=00:00:00.001|Request=det|Category=btyjar<br> Time=00:00:00.002|Request=sdf|Category=345<br> Time=00:00:00.003|Request=fdgh|Category=cvn<br> Time=00:00:00.004|Request=cv|Category=ryui<br> log2.log<br> --------<br> Time=00:00:00.001|Request=h5|Category=56yjh<br> Time=00:00:00.002|Request=hjk|Category=dr6<br> Time=00:00:00.003|Request=qw|Category=345<br> Time=00:00:00.004|Request=thgj|Category=234<br>

        ok, that's example data. then to collect the data i use:

        for my $log (@logs) { if ($log =~ /\.gz$/) { eval "`gunzip $log`"; next if $@; $log = substr $log, 0, -3; } open(LOG,$log) || warn "log not opened\n"; while (<LOG>) { chomp; my @data = split /\|/; for (@data) { my($cat,$value) = split /=/; $logdata{$log}{$.}{lc($cat)} = $value; } } close LOG; }

        output is in one of two forms: log by log (so i do a little "1 of 10", "previous", "next" to switch between) or Merged - all the files in one big table. both output formats need to be sortable. the log by log is easy because I am sorting at the line level but the merged table is where I got stuck.

        I do have many lines and so I need to find a way to get the sort to iterate through those lines, pulling out the time and comparing it, while still at the log level to find out in which order to sort all of the lines of all of the logs.

        cheers for taking the time to look at this.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (None)
    As of 2024-04-25 00:23 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      No recent polls found