Re: Sorting year and month

2005-03-02 Thread Sherm Pendley
On Mar 2, 2005, at 12:14 AM, John Horner wrote:
@data = sort {
$a-{year} = $b-{year}
  ||
$months{ $a-{month} } = $months{ $b-{month} }
} @data;
## only if the years are equal does the second sort take place, is 
that right?
Yes - when you use ||, it short circuits the expression if the first 
part is true. Conversely, when you use , it short circuits if the 
first part is false.

sherm--
Cocoa programming in Perl: http://camelbones.sourceforge.net
Hire me! My resume: http://www.dot-app.org


Re: Sorting year and month

2005-03-01 Thread Sherm Pendley
On Mar 1, 2005, at 2:48 AM, Mark Wheeler wrote:
Hi Sherm,
That works perfectly. Could you give me a brief rundown on how the 
sort works with Date::Manip, so I can understand what is going on?

On Feb 28, 2005, at 1:03 AM, Sherm Pendley wrote:
my @sorted = sort { Date_Cmp(ParseDate($b), ParseDate($a)); } 
@dates;
I'm not certain how much detail you need, so I'll start at the 
beginning, with sort(). Sort() allows you to provide a block of code 
that's used as a comparison function. Two arguments are passed to that 
function - $a and $b - and the return value should mimic that of = or 
cmp - that is,  0 if $a  $b, 0 if $a == $b, and  0 if $a  $b.

So, suppose we have a list of hashes, like this:
my @garbled = (
{ 'foo'='trouble', 'sort_by'=3 },
{ 'foo'='hubble', 'sort_by'=0 },
{ 'foo'='toil', 'sort_by'=2 },
{ 'foo'='bubble', 'sort_by'=1 },
);
We could sort it according to the sort_by field like this:
my @spell = sort { $a-{'sort_by'} = $b-{'sort_by'} } @garbled;
Note that there's no comma between the comparison function and 
@garbled. If there were, Perl would treat the block as the first 
element in the list to be sorted. Also, $a and $b are magic - you don't 
have to declare them with my() or our(), or shift them off of @_. 
They're just there. Also, strict knows about them, although not in 
detail; you can use an undeclared $a or $b *anywhere*, not just with a 
sort(), without hearing a peep from strict.

So anyway, how's that work with Date::Manip?
The ParseDate() function takes a date in a variety of formats, and 
returns it in a normalized format: mmddhh:mm:ss. Date_Cmp() 
compares two of these normalized date strings, and returns a value 
that's consistent with = or cmp - that is, 0, 0, or 0 - as expected 
by sort.

You *could* simply use cmp to compare these strings - in fact that's 
basically all Date_Cmp() does right now - but the Date::Manip docs 
indicate that the normalized format will be extended at some future 
point, to include various flags such as the time zone. At that point, 
Date_Cmp() will also be updated to take the flags into account, whereas 
cmp will no longer work. So, using Date_Cmp() is optional at the 
moment, but it's more future-proof than cmp.

sherm--
Cocoa programming in Perl: http://camelbones.sourceforge.net
Hire me! My resume: http://www.dot-app.org


Re: Sorting year and month

2005-03-01 Thread Mark Wheeler
Hi Sherm,
Thanks for taking the time to explain it. That makes sense.
Mark
On Mar 1, 2005, at 12:59 AM, Sherm Pendley wrote:
On Mar 1, 2005, at 2:48 AM, Mark Wheeler wrote:
Hi Sherm,
That works perfectly. Could you give me a brief rundown on how the 
sort works with Date::Manip, so I can understand what is going on?

On Feb 28, 2005, at 1:03 AM, Sherm Pendley wrote:
my @sorted = sort { Date_Cmp(ParseDate($b), ParseDate($a)); } 
@dates;
I'm not certain how much detail you need, so I'll start at the 
beginning, with sort(). Sort() allows you to provide a block of code 
that's used as a comparison function. Two arguments are passed to that 
function - $a and $b - and the return value should mimic that of = or 
cmp - that is,  0 if $a  $b, 0 if $a == $b, and  0 if $a  $b.

So, suppose we have a list of hashes, like this:
my @garbled = (
{ 'foo'='trouble', 'sort_by'=3 },
{ 'foo'='hubble', 'sort_by'=0 },
{ 'foo'='toil', 'sort_by'=2 },
{ 'foo'='bubble', 'sort_by'=1 },
);
We could sort it according to the sort_by field like this:
my @spell = sort { $a-{'sort_by'} = $b-{'sort_by'} } @garbled;
Note that there's no comma between the comparison function and 
@garbled. If there were, Perl would treat the block as the first 
element in the list to be sorted. Also, $a and $b are magic - you don't 
have to declare them with my() or our(), or shift them off of @_. 
They're just there. Also, strict knows about them, although not in 
detail; you can use an undeclared $a or $b *anywhere*, not just with a 
sort(), without hearing a peep from strict.

So anyway, how's that work with Date::Manip?
The ParseDate() function takes a date in a variety of formats, and 
returns it in a normalized format: mmddhh:mm:ss. Date_Cmp() 
compares two of these normalized date strings, and returns a value 
that's consistent with = or cmp - that is, 0, 0, or 0 - as expected 
by sort.

You *could* simply use cmp to compare these strings - in fact that's 
basically all Date_Cmp() does right now - but the Date::Manip docs 
indicate that the normalized format will be extended at some future 
point, to include various flags such as the time zone. At that point, 
Date_Cmp() will also be updated to take the flags into account, whereas 
cmp will no longer work. So, using Date_Cmp() is optional at the 
moment, but it's more future-proof than cmp.

sherm--
Cocoa programming in Perl: http://camelbones.sourceforge.net
Hire me! My resume: http://www.dot-app.org


Re: Sorting year and month

2005-03-01 Thread John Horner
I was interested by this question -- and let me say, of course the 
correct answer is, use the module -- I just took the opportunity to 
try learn a bit about more advanced sorting.

The following is of course a very roundabout solution, but it shows 
how you can sort by an arbitrary quality you assign yourself (as you 
might if you wanted to sort the months from financial year to 
financial year where April might be 1 and March 12) and how to 
sub-sort.

I'd appreciate your comments.
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
use Data::Dumper;
my %months = ( Jan = 1, Feb = 2, Mar = 3, Apr = 4 );
## Assign values to the month names,
## I'm too lazy to do the whole 12.
my @dates = qw(
  Apr-2005 Feb-2001 Mar-2001
  Jan-2004 Jan-2005 Mar-2005
  Feb-2003 Mar-2003 Apr-2003
  Mar-1999 Apr-1999 Feb-2002
);
## randomly chosen dates in random order
my @data = ();
for ( @dates ) {
my ( $m, $y ) = split( '-', $_ );
push( @data, { year = $y, month = $m } );
}
## build AoH from dates
@data = sort {
$a-{year} = $b-{year}
  ||
$months{ $a-{month} } = $months{ $b-{month} }
} @data;
## only if the years are equal does the second sort take place, is that right?
print Dumper( [EMAIL PROTECTED] );
## seems to work:
# $VAR1 = [
#   {
# 'month' = 'Mar',
# 'year' = 1999
#   },
#   {
# 'month' = 'Apr',
# 'year' = 1999
#   },
#   {
# 'month' = 'Feb',
# 'year' = 2001
#   },
#   {
# 'month' = 'Mar',
# 'year' = 2001
#   },
#   {
# 'month' = 'Feb',
# 'year' = 2002
#   },
#   {
# 'month' = 'Feb',
# 'year' = 2003
#   },
#   {
# 'month' = 'Mar',
# 'year' = 2003
#   },
#   {
# 'month' = 'Apr',
# 'year' = 2003
#   },
#   {
# 'month' = 'Jan',
# 'year' = 2004
#   },
#   {
# 'month' = 'Jan',
# 'year' = 2005
#   },
#   {
# 'month' = 'Mar',
# 'year' = 2005
#   },
#   {
# 'month' = 'Apr',
# 'year' = 2005
#   }
# ];
#



Sorting year and month

2005-02-28 Thread Mark Wheeler
Hi,
I have a quick question regarding sorting. I have a list of dates and 
years in the following format:

October-2004
December-2004
September-2004
January-2005
November-2004
I need to sort them so the final outcome is:
January-2005
December-2004
November-2004
October-2004
September-2004
Of course the list will eventually include all 12 months, but the above 
is just an example. What is the best way to go about doing this? I'm 
not too familiar with using sort, but I'm sure that is the way to go. 
Any help would be appreciated.

Thanks,
Mark


Re: Sorting year and month

2005-02-28 Thread Mark Wheeler
Hi Sherm,
That works perfectly. Could you give me a brief rundown on how the sort 
works with Date::Manip, so I can understand what is going on?

Thanks,
Mark
On Feb 28, 2005, at 1:03 AM, Sherm Pendley wrote:
On Feb 28, 2005, at 3:41 AM, Mark Wheeler wrote:
I have a quick question regarding sorting. I have a list of dates and 
years in the following format:

October-2004
December-2004
September-2004
January-2005
November-2004
I need to sort them so the final outcome is:
January-2005
December-2004
November-2004
October-2004
September-2004
Of course the list will eventually include all 12 months, but the 
above is just an example. What is the best way to go about doing this? 
I'm not too familiar with using sort, but I'm sure that is the way 
to go. Any help would be appreciated.
Have a look at Date::Manip - it has date parsing and comparison 
functions you can use with sort(). Example:

#!/usr/bin/perl
use warnings;
use strict;
use Date::Manip;
my @dates = qw(
October-2004
December-2004
September-2004
January-2005
November-2004
);
my @sorted = sort { Date_Cmp(ParseDate($b), ParseDate($a)); } 
@dates;

for (@sorted) { print $_, \n; }
sherm--
Cocoa programming in Perl: http://camelbones.sourceforge.net
Hire me! My resume: http://www.dot-app.org