Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:
Hi Monks!
I am trying to search by date here on this:
@stuff = (
{"submitted","01/22/08"},
{"submitted","01/12/08"},
{"submitted","04/01/09"},
{"submitted","10/04/08"},
{"submitted","01/10/09"},
{"submitted","12/12/09"},
{"submitted","01/22/09"},
{"submitted","01/12/09"},
{"submitted","12/30/08"},
{"submitted","12/22/08"},
{"submitted","12/15/08"},
{"submitted","01/05/09"},
{"submitted","01/19/09"},
{"submitted","01/21/09"}
);
@newstuff = sort bydte @stuff;
foreach $pers (@newstuff) {
print $$pers{submitted}."\n";
}
sub bydte {
$$a{submitted} <=> $$b{submitted};
#$$a{submitted} cmp $$b{submitted};
}
And my goal is to get all the most recent dates on top, I tried and no luck. Any help?
Thanks for the Help!
Re: Sorting by Date Help!
by moritz (Cardinal) on Mar 17, 2009 at 18:34 UTC
|
$$a{submitted} <=> $$b{submitted};
<=> does numeric comparison, so your code will only compare by the first number in the string. Transform your data into a format like 08-02-28, then you can use simple string comparison to get correct date comparison.
| [reply] [d/l] [select] |
|
Still did not work, but another question to try to simplify what I am asking is if a had a Array of Hashes, like:
my @data;
push @data, {name => "Submitted", date => 01/03/08 };
push @data, { name => "Submitted", date => 04/04/09 };
push @data, { name => "Submitted", date => 12/01/08};
push @data, { name => "Submitted", date => 12/01/09};
push @data, { name => "Submitted", date => 08/10/08};
my @sorted = sort { $a->{date} <=> $b->{date} } @data;
Would that sort by the most recent date? | [reply] [d/l] |
|
Still did not work
In what way? I'm surprised... show us what code you've tried, so that we can tell you what's wrong and how to fix it.
push @data, {name => "Submitted", date => 01/03/08 };
If you write 01/03/08 it will complain with Illegal octal digit '8' at.
Would that sort by the most recent date?
No, because you still haven't fixed the comparison semantics.
| [reply] [d/l] [select] |
|
|
Re: Sorting by Date Help!
by almut (Canon) on Mar 17, 2009 at 19:54 UTC
|
my @stuff = (
{submitted => "01/22/08"},
{submitted => "01/12/08"},
{submitted => "04/01/09"},
{submitted => "10/04/08"},
{submitted => "01/10/09"},
{submitted => "12/12/09"},
{submitted => "01/22/09"},
{submitted => "01/12/09"},
{submitted => "12/30/08"},
{submitted => "12/22/08"},
{submitted => "12/15/08"},
{submitted => "01/05/09"},
{submitted => "01/19/09"},
{submitted => "01/21/09"}
);
my @sorted =
map { $_->[0] }
sort { $b->[1] cmp $a->[1] }
# map { print "$_->[1]\n"; $_ } # uncomment for debugging purposes
map { [$_, join('', (split(/\//, $_->{submitted}))[2,0,1] )] }
@stuff;
foreach my $res (@sorted) {
print $res->{submitted}."\n";
}
See Schwartzian Transform | [reply] [d/l] |
|
It worked, if you would have to explain this code to someone, would the "Schwartzian Transform" link be the place to start? Thanks for the help!
| [reply] |
|
would the "Schwartzian Transform" link be the place to start?
Yes, I think so, as from there you'll
also find a link to the original Unix Review column.
The latter explains it in detail, but the PerlMonks thread provides additional discussion...
What isn't explained there is the specific implementation of the "expensive_func" being used here. So just in case :)
join('', (split(/\//, $_->{submitted}))[2,0,1] )
This splits the date strings by "/", rearranges the three parts so that year comes first, then month, then day (which makes the dates easily sortable by string comparison), and joins them into a single string like "080122" (for 01/22/08). The (...)[2,0,1] construct is described in perldata (search for "list slice"). | [reply] [d/l] [select] |
Re: Sorting by Date Help!
by poolpi (Hermit) on Mar 17, 2009 at 22:11 UTC
|
use strict;
use warnings;
use DateTime;
my @sorted_dates = sort {
DateTime->compare_ignore_floating($$b{'submitted'}, $$a{'submitted'})
} map {
my ( $month, $day, $year ) = ( split( '/', $_ ) )[ 0 .. 2 ];
{
qq(submitted),
DateTime->new(
year => $year + 2000,
month => $month,
day => $day,
time_zone => 'Europe/Paris',
)
}
} qw{ 01/22/08 01/12/08 04/01/09 10/04/08 01/10/09 12/12/09 01/22/0
+9 01/12/09 12/30/08 12/22/08 12/15/08 01/05/09 01/19/09 01/21/09};
print $sorted_dates[$_]{'submitted'}->mdy('/'), "\n"
for 0 .. $#sorted_dates;
__END__
Output:
12/12/2009
04/01/2009
01/22/2009
01/21/2009
01/19/2009
01/12/2009
01/10/2009
01/05/2009
12/30/2008
12/22/2008
12/15/2008
10/04/2008
01/22/2008
01/12/2008
hth, PooLpi
| [reply] [d/l] |
Re: Sorting by Date Help!
by VinsWorldcom (Prior) on Mar 17, 2009 at 19:55 UTC
|
I may be misunderstanding how you want it sorted, but if you keep the date format you have, you won't be able to sort how you (I think) want.
12-01-08
01-01-07
12-01-06
01-01-98
will sort:
01-01-07
01-01-98
12-01-06
12-01-08
It will sort all the January's first, then all the Februarys, etc... Result will be that January 1998, comes before December 2008, which is not what you want - I'm guessing. If you reverse order, you'd get all the December's first which would make December 2006 come before January 2007. Still not correct.
Have you tried using a different date format - or using Perl to convert the dates you have to a sortable format and then printing them back the way you want?
IMHO, the best way to sort dates would be: YYYYMMDD. | [reply] [d/l] [select] |
|
|