You could replace the sort and nsort virtual methods with your own.
The below example uses Data::Sorting which is available from CPAN.
Template usage example:
[% FOREACH person = people.sort('last_name', 'first_name', 'middle_initial') %]
or
[% FOREACH person = people.nsort('area_code', 'postal_code', 'age') %]
Caveats:
For speed reasons, sorting on 0 or 1 keys will use the original
sorting method, and sorting on 2 or more keys uses the new one.
Initial tests indicate the multi-key sort is about five times
slower than a native perl sort().
Also, please note that this new sort does not automatically
Do The Right Thing when operating on an array of blessed objects.
Sorting in the underlying Data::Sorting module only operates on
hash values. Fixing this deficiency is left as an exercise.
##
use strict;
use Template;
use Data::Sorting ':arrays';
$Template::Stash::LIST_OPS->{'sort'} = sub {
$^W = 0;
my ($list, @fields) = @_;
return $list unless @$list > 1; # no need to sort 1 item lists
if (@fields > 1) {
return [
sorted_arrayref (
$list, -compare => 'textual', map { -sortkey => $_ } @fields
)
];
} else {
my $field = $fields[0];
return @fields # Schwartzian Transform
? map { $_->[0] } # for case insensitivity
sort { $a->[1] cmp $b->[1] }
map { [ $_, lc(ref($_) eq 'HASH'
? $_->{ $field } :
UNIVERSAL::can($_, $field)
? $_->$field() : $_) ] }
@$list
: map { $_->[0] }
sort { $a->[1] cmp $b->[1] }
map { [ $_, lc $_ ] }
@$list;
}
};
$Template::Stash::LIST_OPS->{'nsort'} => sub {
my ($list, @fields) = @_;
return $list unless @$list > 1; # no need to sort 1 item lists
if (@fields > 1) {
return [
sorted_arrayref (
$list, -compare => 'numeric', map { -sortkey => $_ } @fields
)
];
} else {
my $field = $fields[0];
return @fields # Schwartzian Transform
? map { $_->[0] } # for case insensitivity
sort { $a->[1] <=> $b->[1] }
map { [ $_, lc(ref($_) eq 'HASH'
? $_->{ $field } :
UNIVERSAL::can($_, $field)
? $_->$field() : $_) ] }
@$list
: map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [ $_, lc $_ ] }
@$list
}
};
# process template at this point
$template->process (...);
##
Peter Guzis
Web Administrator, Sr.
ENCAD, Inc.
- A Kodak Company
email: [EMAIL PROTECTED]
www.encad.com
-----Original Message-----
From: Brett Sanger [mailto:[EMAIL PROTECTED]
Sent: Thursday, March 04, 2004 1:44 PM
To: [EMAIL PROTECTED]
Subject: [Templates] sort by multiple criteria?
So I have an array of hashrefs, that have date-related data (frex:
Month and year)
I've been asked to sort the output in most-recent-first order.
I tried:
[% FOREACH Report = Reports.nsort('year').nsort('month') %]
(I expected this to be backwards, but I figured I'd mess with reverse
once I was sure this worked)
This didn't quite work as expected. I got the results I wanted with:
[% FOREACH Report = Reports.nsort('month').nsort('year').reverse %]
But I'm not sure that that's not just an artifact of my data.
The docs (Template::Manual::VMethods) don't seem to talk about
"stacking" vmethods...what is the expected order of resolution? Does
the sort vmethod respect the previous order where there is no change
required?
TIA
--
SwiftOne / Brett Sanger
[EMAIL PROTECTED]
_______________________________________________
templates mailing list
[EMAIL PROTECTED]
http://lists.template-toolkit.org/mailman/listinfo/templates
_______________________________________________
templates mailing list
[EMAIL PROTECTED]
http://lists.template-toolkit.org/mailman/listinfo/templates