in reply to Re: Re: sorting hash of hashes
in thread sorting hash of hashes

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

Replies are listed 'Best First'.
re: readibility
by larryk (Friar) on Apr 25, 2001 at 21:01 UTC
    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.

      Still a little confused... do you want to sort by log, then by other data? If that is the case you need to use two sorts... do an outer loop to sort by log, then an inner loop to sort by your other data using the log from the first sort...
                      - Ant
        I need to sort all of the lines in all of the logs by the time on each line. so I need to sort $logdata->{log1..logN} by getting Perl's sort to compare $logdata->{$a}->{$line1..$lineN}->{'time'} to $logdata->{$b}->{$line1..$lineN}->{'time'}

        If I first sort the logs and then do an inner sort on time then I will still have segregation by log but I have to put it all together so if an event happened at 12:00:43.001 in the 3rd log, it will appear above the event at 13:34:23.843 in the 1st log, but below the event at 04:04:21.891 in the 7th log.

        larryk