Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Sorting Dates Issue

by Anonymous Monk
on Aug 18, 2010 at 15:34 UTC ( #855815=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks!
I have this array with dates but having problems with my sort code, here is an example about what its goign in on:
#!/usr/bin/perl user strict; my @dates = ('10/02/2004', '02/01/2004', '01/02/2004', '01/06/2004', ' +01/02/2005', '01/12/2004', '08/18/2010'); my @ordered = sort { &compare } @dates; sub compare { $a =~ /(\d{2})\/(\d{2})\/(\d{4})/; $c = $3 . $1 . $2; $b =~ /(\d{2})\/(\d{2})\/(\d{4})/; $c = $3 . $1 . $2; $c <=> $d; } print "@ordered\n";

I got this:
08/18/2010 01/12/2004 01/02/2005 01/06/2004 01/02/2004 02/01/2004 10/02/2004

This date "01/02/2005" is off, I guess the sorting is not reaching the years, any suggestions? Thanks for the help!

Replies are listed 'Best First'.
Re: Sorting Dates Issue
by johngg (Canon) on Aug 18, 2010 at 17:37 UTC

    Your idea of extracting year, month and day then concatenating them so they sort naturally is fine. You could take it a little further and apply a Guttman Rosler Transform instead of a sort routine. This node has an explanation and this is the paper on the technique. I think split might be an easier way of extracting date elements than a regex.

    knoppix@Microknoppix:~$ perl -E ' > @dates = qw{ > 10/02/2004 > 02/01/2004 > 01/02/2004 > 01/06/2004 > 01/02/2005 > 01/12/2004 > 08/18/2010 > }; > say for > map { substr $_, 8 } > sort > map { join q{}, ( split m{/} )[ 2, 0, 1 ], $_ } > @dates;' 01/02/2004 01/06/2004 01/12/2004 02/01/2004 10/02/2004 01/02/2005 08/18/2010 knoppix@Microknoppix:~$

    I hope this is of interest.

    Cheers,

    JohnGG

      Yes it works, how could this code do the sorting in reverse, I mean the most recent date on top?
      use strict; my @dates = qw{ 10/02/2004 02/01/2004 01/02/2004 08/18/2010 01/06/2004 01/02/2005 01/12/2004 }; my @sorted= map { substr $_, 8 } sort map { join q{}, ( split m{/} )[ 2, 0, 1 ], $_ }@dates;

      Thanks!

        Once the elements to be sorted have been combined into a single string it is just a lexical sort so you can use a simple anonymous routine to reverse the order.

        knoppix@Microknoppix:~$ perl -E ' > @dates = qw{ > 10/02/2004 > 02/01/2004 > 01/02/2004 > 01/06/2004 > 01/02/2005 > 01/12/2004 > 08/18/2010 > }; > say for > map { substr $_, 8 } > sort { $b cmp $a } > map { join q{}, ( split m{/} )[ 2, 0, 1 ], $_ } > @dates;' 08/18/2010 01/02/2005 10/02/2004 02/01/2004 01/12/2004 01/06/2004 01/02/2004 knoppix@Microknoppix:~$

        Cheers,

        JohnGG

Re: Sorting Dates Issue
by ikegami (Pope) on Aug 18, 2010 at 15:42 UTC
    The could you posted definitely did not produce the output you said it did. It doesn't even run. If you fix the errors that must be fixed simply to get your code to run (use strict, undeclared $c, undeclared $d), it works fine. Please post code you actually ran!! The code you posted is so far from what you really have, there's no way of telling what your problem is.
Re: Sorting Dates Issue
by Utilitarian (Vicar) on Aug 18, 2010 at 15:47 UTC
    You claim this is your code:
    use strict; ... sub compare { $a =~ /(\d{2})\/(\d{2})\/(\d{4})/; $c = $3 . $1 . $2; $b =~ /(\d{2})\/(\d{2})\/(\d{4})/; $c = $3 . $1 . $2; $c <=> $d; }
    However there are no default variables $c or $d so your code would not run.

    The fact that you assign the two compound numbers to the same variable may be your issue, use warnings; would have noted this.

    print "Good ",qw(night morning afternoon evening)[(localtime)[2]/6]," fellow monks."
Re: Sorting Dates Issue
by dasgar (Priest) on Aug 18, 2010 at 15:54 UTC

    In your subroutine, you have $c <=> $d;. However, I don't see $d being declared or defined anywhere. I haven't tested your code, but this line looks like a good candidate for causing problems.

    Also, you should change user strict; to use strict;, which I believe would have prevented you from using variables in your subroutine without using my or our. (see docs on strict)

Re: Sorting Dates Issue
by jethro (Monsignor) on Aug 18, 2010 at 15:55 UTC

    Please 'use warnings;', that would have brought you the following warnings:

    Name "main::d" used only once: possible typo at ./t7.pl line 16. Can't locate object method "user" via package "strict" (perhaps you fo +rgot to load "strict"?) at ./t7.pl line 3.

    And $d in the first warning is the problem, it is never set, instead you are setting $c twice

    The other warning is because you wrote 'user' instead of 'use'

    PS: Your sort line might be better written as my @ordered = sort compare  @dates;. As you have it, sort calls the "block-subroutine" which in turn calls the compare subroutine. It is possible that perl optimizes this away but I wouldn't bet on it.

      Has anyone here sorted an array with dates to show how it can get done?
        I did test the script after correcting those two mistakes. Since the changes are trivial I didn't think it necessary to repost the script
Re: Sorting Dates Issue
by murugu (Curate) on Aug 18, 2010 at 17:48 UTC
    This is off topic. I never used a date module before. Tried with Date::Simple
    use Date::Simple qw(:all); my @dates = ('10/02/2004', '02/01/2004', '01/02/2004', '01/06/2004', ' +01/02/2005', '01/12/2004', '08/18/2010', '01/05/2005', '01/05/2004',' +01/05/2004'); @dates = map {$_->[0]} sort { &date($a->[1]) cmp &date($b->[1]) } map + {[$_, join '-',(split '/')[2,0,1]]} @dates; print $_,$/ for (@dates);

    Regards,
    Murugesan Kandasamy
    use perl for(;;);

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (3)
As of 2021-11-29 16:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?