On Thu, 2006-11-09 at 08:47 -0500, Zielfelder, Robert wrote:
> Greetings:
> 
>  
> 
> I have a sorting problem I need to solve but I'm not sure how to go
> about it.  I have an application that dumps a file with a format like
> this:
> 
>  
> 
> 19JAN2006.1503
> 
> 03JAN2006.1647
> 
> 19DEC2004.0530
> 
> 24MAR2003.1115
> 
>  
> 
> 
> 
> As you may have guessed, these are dates and times - timestamps for log
> files from an application.  I want to be able to sort this list from
> earliest to latest date.  I'm able to parse these into specific
> categories (Year, Month, Day, Time) and can sort on any one category,
> but I don't know how to sort by multiple categories.  Anyone have any
> ideas?
> 
>  
> 
> Thanks,
> 
>  
> 
> Rz

I know some Perl mongers have already answered this. Though I've seen
some non-satisfying ways in the examples. Now, I'm not saying my way is
the best way, but it's a real multilevel sort. You can indeed have a
multilevel sort. So here's how I would have done it:

--- Begin code ---

#!/usr/bin/perl -w
use strict;
my @files = qw(
    19JAN2006.1503
    03JAN2006.1647
    25DEC2001.0001
    19DEC2004.0530
    24MAR2003.1115
    21MAY2003.0554
);
my %files_date;

for (@files) {
    $files_date{$_} = [/(\d{2})(.{3})(\d{4})\.?(\d{4})/];
}

## the code below is used so that you can see
## the values of each key in the %files_date hash:
#for my $key (keys %files_date) {
#   for my $value (@{$files_date{$key}}) {
#       print "$key => $value\n";
#   }
#}

my @sorted_files = sort {
    $files_date{$a}[2] <=> $files_date{$b}[2] # by year
        or
    $files_date{$a}[1] cmp $files_date{$b}[1] # by month
        or
    $files_date{$a}[0] <=> $files_date{$b}[0] # by day
        or
    $files_date{$a}[3] cmp $files_date{$b}[3] # by time
} keys %files_date;

for (@sorted_files) {
    print "$_\n";
}

--- End of code ---

--- Output ---

25DEC2001.0001
24MAR2003.1115
21MAY2003.0554
19DEC2004.0530
03JAN2006.1647
19JAN2006.1503

-- End of output ---

Now, that is a multilevel sort. You can rearrange it to suit your needs,
sort it by time first or by month, whatever you wish. If you wish the
youngest files to show up first, all you have to do is "reverse" the
sort by checking $b before $a, there's no need for the reverse operator.

Example:

--- Code ---

my @sorted_files = sort {
    $files_date{$b}[2] <=> $files_date{$a}[2] # by year
        or
    $files_date{$b}[1] cmp $files_date{$a}[1] # by month
        or
    $files_date{$b}[0] <=> $files_date{$a}[0] # by day
        or
    $files_date{$b}[3] cmp $files_date{$a}[3] # by time
} keys %files_date;

--- End of code ---

--- Output ---

03JAN2006.1647
19JAN2006.1503
19DEC2004.0530
24MAR2003.1115
21MAY2003.0554
25DEC2001.0001

--- End of output ---

See the difference? Compare the two (both the code and the output). The
possibilities are endless. :-)

Of course my code assumes you have at least a basic knowledge of
references, see "perldoc perlreftut" or go to
http://perldoc.perl.org/perlreftut.html . For the on-line documentation.

I can explain my solution in full detail if you'd like. I'll be more
than happy to do so. :-)


-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to