[Templates] sorting a multi-valued hash
Josh Rosenbaum
josh@infogears.com
Thu, 24 Aug 2006 10:08:07 -0600
Jonathan Mangin wrote:
> Is it possible to sort a multi-valued hash?
> In psuedo-code (all cols are text):
>
> $menu{id} = [concat(col2,col3), col2, col3];
>
> I hoped it would default to sorting on value.0, but output
> appears random.
>
> [% FOREACH item IN menu.sort %]
> [% IF menu.$item.1 == rows.0.1 %]
> <option value="[% item %]" selected>[% menu.$item.0 %]
> [% ELSE %]
> <option value="[% item %]">[% menu.$item.0 %]
> [% END %]
> [% END %]
>
> Two (or more) of these constructs in the template sort in
> the same order. It must not be random but I can't see the
> pattern. Is there anything else I can do to get a sort on
> value.0?
I think you'll need to create your own hash virtual method, or use a different structure.
Something like this might work:
menu = [
{id => 'xxx', column1 => concat(col2,col3), columns => [col2, col3]},
{id => 'xxx', column1 => concat(col2,col3), columns => [col2, col3]},
{id => 'xxx', column1 => concat(col2,col3), columns => [col2, col3]},
]
Then [% FOREACH item IN menu.sort('column1') %]
Here's an example vmethod that works on your hash above. (Well maybe. I didn't test or think about it much):
$Template::Stash::HASH_OPS->{ sort_array } = sub {
my ($hash, $index) = @_;
return sort {$hash->{$a}->[$index] cmp $hash->{$b}->[$index] } keys %$hash;
};
Usage: [% FOREACH item IN menu.sort_array(0) %]
Of course you might want to make it a bit more robust than that, or change it to suit your needs.
-- Josh