Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

sort based on date

by suhailck (Friar)
on Aug 08, 2010 at 15:25 UTC ( [id://853656]=perlquestion: print w/replies, xml ) Need Help??

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

Hi all,

I have one requirement of sorting array elements based on date.

The date format is as follows,

"Aug 8 12:12:13"
"Jan 1 21:01:03"

I have written the following code to perform this task,

perl -MDate::Manip -e '@arr=("Aug 8 12:12:13","Jan 1 21:01:03", "Aug 8 12:12:14","Aug 7 09:12:10"); print map {$_->[0],"\n" } sort { $b->[1] <=> $a->[1] } map {my $c=ParseDateString($_);$c=~s/://g;[$_,$c]} @arr' Aug 8 12:12:14 Aug 8 12:12:13 Aug 7 09:12:10 Jan 1 21:01:03


This works for me, but im looking for an alternative which is more effecient or better than mine.

Thanks,

~suhail

Replies are listed 'Best First'.
Re: sort based on date
by CountZero (Bishop) on Aug 08, 2010 at 16:11 UTC
    You have made a fine application of the Schwartzian Transform. The only speed improvement I can think of is replacing the ParseDateString-function by something with less overhead (perhaps a regex made specifically for this format of dates).

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: sort based on date
by ikegami (Patriarch) on Aug 08, 2010 at 18:18 UTC

    I suspect this is a case of premature optimisation, but assuming this really is a bottleneck, the biggest loss of time would be calling the Perl compare function repeatedly. Using a basic lexical or numerical sort would be better. (The default callback, { $a cmp $b } and { $a <=> $b } are handled super efficiently.)

    use 5.010; # say use strict; use warnings; use Date::Manip qw( ParseDateString ); my @dates = ( "Aug 8 12:12:13", "Jan 1 21:01:03", "Aug 8 12:12:14", "Aug 7 09:12:10", ); my %lookup; say $lookup{$_} for sort map { $lookup{ my $s = ParseDateString($_) } = $_; $s } @dates;
    And that can be optimised to
    use 5.010; # say use strict; use warnings; use Date::Manip qw( ParseDateString ); my @dates = ( "Aug 8 12:12:13", "Jan 1 21:01:03", "Aug 8 12:12:14", "Aug 7 09:12:10", ); say substr($_, 16) for sort map ParseDateString($_).$_, @dates;

    The following might be faster by taking advantage of internal optimisations.

    use 5.010; # say use strict; use warnings; use Date::Manip qw( ParseDateString ); my @dates = ( "Aug 8 12:12:13", "Jan 1 21:01:03", "Aug 8 12:12:14", "Aug 7 09:12:10", ); $_ = ParseDateString($_).$_ for @dates; @dates = sort @dates; say substr($_, 16) for @dates;

    I also agree with the previous comment about replacing ParseDateString with something tailored to your needs. Mind you, if you write the replacement in Perl and if ParseDateString is currently written in C, the replacement could easily be slower.

    I haven't benchmarked anything.

Re: sort based on date
by zentara (Archbishop) on Aug 08, 2010 at 15:55 UTC
Re: sort based on date
by Anonymous Monk on Aug 08, 2010 at 20:09 UTC

    If you are looking for speed, I'd recommend something like this (trading space for time + process your string using native functions):

    my %h1 = ( 'Jan' => 'a', 'Feb' => 'b', ... 'Dec' => 'l', ); my %h2 = ( 'a' => 'Jan', 'b' => 'Feb', ... 'l' => 'Dec', ); my @sorted_dates = grep { s/^(.)(\d\d)/$e{$1} . ' ' . sprintf("%d",$2)/e } sort grep { s/^(.{3}) (\d\d?)/$d{$1} . sprintf("%02d",$2)/e; } @dates;

    Of course you can/must rework the regex'es according to string format. Compared to code using Date::Manip, this one runs ~200 times faster (on my system)

      EDIT: in regex'es $d must be $h1 and $e must be $h2
      my %h1 = ( 'Jan' => 'a', 'Feb' => 'b', ... 'Dec' => 'l', ); my %h2 = ( 'a' => 'Jan', 'b' => 'Feb', ... 'l' => 'Dec', ); my @sorted_dates = grep { s/^(.)(\d\d)/$h2{$1} . ' ' . sprintf("%d",$2)/e } sort grep { s/^(.{3}) (\d\d?)/$h1{$1} . sprintf("%02d",$2)/e; } @dates;

        grep? What are you trying to filter out?

        Anyway, the following manipulations are twice as fast:

        my %month_key_lookup = ( 'Jan' => 'a', 'Feb' => 'b', ... 'Dec' => 'l', ); my @sorted_dates = map substr($_, 12), sort map { /^(.{3}) (\d?)(. .*)/s; $month_key_lookup{$1}.($2||'0').$3.$_ } @dates;

        As a bonus, it doesn't clobber the contents of @dates.

Re: sort based on date
by Marshall (Canon) on Aug 09, 2010 at 03:35 UTC
    If you have a choice about how the date/times are represented, using 24 UTC time in this format will allow you to just do a simple alpha sort on the date/time field. The leading zeroes are important.

    #year-month-day with leading zero'es!
    2010-08-06 13:12:13 # "Aug 6th, 2010 13:12:13" (1 pm+)
    2010-01-01 21:01:03 # "Jan 1, 2010 21:01:03" (9 pm+)

Re: sort based on date
by JavaFan (Canon) on Aug 08, 2010 at 22:21 UTC
    Considering the dates have no years, I'd say any permutation is an equally valid solution.

      A true defeatist would also note the time zone isn't specified either and that double-digit days aren't supported. This problem is truly impossible to solve!

      ++Re^4: sort based on date

      Unless you know all the dates in the set are from the same year.

        Put another way: unless you get the year into your dates, the year will get you just after new year.
        Also, POSIX or equivalent ISO date format YYYY/MM/DD hh:mm:ss is the most portable and most universally understood (human or program), and also best defined for sorting or other date manipulations.
        the hardest line to type correctly is: stty erase ^H
        Unless you know all the dates in the set are from the same year.
        Sure, but no such assumption was stated by the OP. An equally valid assumption would be "next occurrence" of the given dates - one might for instance have to order dates for soccer matches of the coming season.

        My meta point of course is that if people post problems here, they shouldn't hide essential knowledge about the problem (I do assume the OP knows which years the dates are supposed to have).

Re: sort based on date
by suhailck (Friar) on Aug 09, 2010 at 04:29 UTC
    Thanks everyone for your valuable comments :)

    ~suhail

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (3)
As of 2024-04-25 06:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found