On Fri, 2006-11-10 at 00:59 -0500, Arnaldo Guzman wrote: > 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. :-)
Oh, I probably should have added what that sort is actually saying. It basically says: "If the years of the files are equal, sort by month. If the months of the files are equal, sort by day, etc.". And that last check (for the time) should be the space ship operator "<=>" not "cmp", the time is a numerical value. -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] <http://learn.perl.org/> <http://learn.perl.org/first-response>