duskwuff уже объясняет в своем ответе, что вы не можете использовать объекты в качестве хеш-ключей, поскольку они сериализуются, и вы потеряете предметность. Мой ответ основан на этом.
Допустим, у вас есть массив массивов, где каждый внутренний массив содержит пару объектов. Я создал классы Moo для иллюстрации.
package My::Model::Group;
use Moo;
has [qw/id name/] => ( is => 'ro' );
package My::Model::Group::Admin;
use Moo;
has [qw/id name/] => ( is => 'ro' );
package main;
my $groups = [
[
My::Model::Group->new( id => 1, name => 'group1' ) =>
My::Model::Group::Admin->new( id => 1, name => 'foo' )
],
[
My::Model::Group->new( id => 2, name => 'group2' ) =>
My::Model::Group::Admin->new( id => 1, name => 'foo' )
],
[
My::Model::Group->new( id => 3, name => 'group3' ) =>
My::Model::Group::Admin->new( id => 1, name => 'bar' )
],
[
My::Model::Group->new( id => 4, name => 'group4' ) =>
My::Model::Group::Admin->new( id => 1, name => 'foo' )
],
];
Есть четыре пары. Два администратора, четыре группы. Три группы принадлежат администратору foo, а одна — bar. Теперь давайте посмотрим на шаблон.
use Template;
my $tt = Template->new();
$tt->process( \*DATA, { groups => $groups }, \my $output )
or die $tt->error;
print $output;
__DATA__
[%- FOREACH item IN groups -%]
[%- DEFAULT by_admin.${item.1.name} = [] -%]
[%- by_admin.${item.1.name}.push(item.0) -%]
[%- END -%]
[%- FOREACH admin IN by_admin.keys.sort -%]
[%- FOREACH group IN by_admin.$admin -%]
[%- admin %] -> [% group.id %]
[%- END -%]
[%- END -%]
Соответствующей частью, очевидно, является раздел DATA
. Нам нужно реорганизовать структуру данных массива в хэш с администраторами, а затем каждую группу отсортировать по одному из слотов администратора.
Нам не нужно создавать переменную by_admin
. Он будет создан глобально неявно. Но нам нужно установить значение по умолчанию для $by_admin->{$item[0]->name}
(сейчас я использую синтаксис Perl, чтобы его было легче понять). Похоже, что Template Toolkit не поддерживает автовивификацию и ключевое слово DEFAULT
аналогично //=
оператор присваивания в Perl.
Затем мы можем push
первый элемент item
в массив ref, который мы только что создали (если он еще не существовал) внутри элемента hash ref с ключом item.1.name
внутри by_name
.
Как только мы закончим подготовку, все остальное будет простым циклом. Мы повторяем sort
ed keys
из by_admin
, а затем повторите ссылку на массив, которая стоит за этим ключом.
Вот результат:
bar -> 3
foo -> 1
foo -> 2
foo -> 4
Препроцессинг имеет смысл делать не в шаблоне, а в вашем контроллере. Как обычный код Perl, его должно быть легче читать.
my %by_admin;
for my $group (@$groups) {
push @{ $by_admin{ $group->[1]{name} } }, $group->[0];
}
Обратите внимание, что я опустил use strict
и use warnings
для краткости.
person
simbabque
schedule
03.05.2017
FOREACH item IN list
правильно. Но вы хотите перегруппировать их, верно? Это как сводка в Excel. У вас есть что-то вроде{ 1 => 'foo', 2 => 'bar', 3 => 'foo' }
, и вы хотите показать, что у пользователяfoo
есть1, 3
, а уbar
есть2
. Я понял? - person simbabque   schedule 03.05.2017