我正在开发一个使用Template::Toolkit
作为模板引擎的Catalyst应用。一页需要一个相等输入元素的列表。它们可以从数组中获取,但我需要排序顺序和元素的描述性标签。
对于排序顺序,我会使用数组。为了存储每个键的附加值,散列是完美的。如何结合TT 中的?我可以使用这两种东西,但这看起来很难看,并且在更改字段时会导致错误。
但是,我更喜欢在TT中这样做,因为表单元素的描述和顺序都是前端的。
这就是我在纯Perl中的表现:
#!/usr/bin/perl -w
use 5.10.0;
# definition of description and order in 1 step
my @fields = (
property_foo => "Some property",
property_bar => "Important field",
property_baz => "Something else",
);
# extract information
my %descriptions = @fields;
my @order = @fields[grep {($_ + 1) % 2} 0..(scalar @fields - 1)];
say "=== natural perl sort order ===";
foreach (keys %descriptions) {say $_};
say "=== wanted output ===";
foreach (@order) {
say $descriptions{$_} . ": [label for $_]";
}
输出:
=== natural perl sort order ===
property_baz
property_foo
property_bar
=== wanted output ===
Some property: [label for property_foo]
Important field: [label for property_bar]
Something else: [label for property_baz]
这是我在模板中写的内容:
[%
order = (
property_foo,
property_bar,
property_baz,
);
descriptions = {
property_foo => "Some property",
property_bar => "Important field",
property_baz => "Something else",
}
FOREACH property IN order %]
[% descriptions.$property %]: <input name="[% property %]" />
[% END %]
但是,拥有相同的信息(字段列表)两次真的很难看。我想避免两次编辑列表,并使用更长的字段列表,它真的很烦人(大约20项,不足以做一些数据库的东西)。
答案 0 :(得分:3)
令人惊讶的是人们如何使简单的东西复杂化!
您不需要@fields数组。请阅读关于键,值和排序的perldoc。
# untested sketch
my %description = ( prop23 => "foo", prop24 => "bar" );
foreach my $key(sort (keys %description)) {
print $key, " is: ", $description{$key}, "\n"; # or whatever
}
附录:关于密钥的顺序,请执行以下操作:
my @arbitraryOrder = qw(prop42 prop35 prop1 ...); # allows to map number to key
my %keytoNumber = (); # will map keys to numbers
foreach my $i(0..$#arbitraryOrder) $keyToNumber{$arbitraryOrder[$i]} = $i;
编写用于排序的比较函数留作练习:)
答案 1 :(得分:3)
您可能对Tie::IxHash
感兴趣这是一个“哈希”,它保持添加键的顺序(值更新不影响排序)。
编辑:一个简短的例子:
use warnings;
use strict;
use Tie::IxHash;
tie my %H, "Tie::IxHash";
$H{foo} = 1;
$H{bar} = 2;
# order of keys is now always 'foo', 'bar'
print keys %H;
EDIT2:我已经尝试过了,它确实有效:
#!/usr/bin/perl -w
use strict;
use Template;
use Tie::IxHash;
# my %h; # this breaks ordering
tie my %H, "Tie::IxHash"; # this keeps ordering
@H{qw/f oo b a r/} = 1..100;
# don't define $H{'keys'} or you'll get disappointed
my $tpl = Template->new();
$tpl->process(\*DATA, {hash=>\%H});
__DATA__
[% FOREACH k IN hash.keys %]
[% k %] => [% hash.$k %]
[% END %]
答案 2 :(得分:1)
如果您需要订购和多条信息,那么您应该考虑一组哈希引用。
my @fields = (
{ id => 'property_foo',
label => 'Some property' },
{ id => 'property_bar',
label => 'Important field' },
{ id => 'property_baz',
label => 'Something else' },
);
foreach (@fields) {
print "ID: $_->{id}, Label: $_->{label}\n";
}
如果复杂性增加很多,您可以考虑用实际对象替换hashref。
而且,在TT中,它看起来像这样:
[%-
properties = [
{id => 'property_foo',
label => 'Some property'},
{id => 'property_bar',
label => 'Important field'},
{id => 'property_baz',
label => 'Something else'},
];
-%]
[%- FOREACH property IN properties %]
[% property.label %]: <input name="[% property.id %]" />
[% END %]
答案 3 :(得分:1)
实际上,如果您希望按键按字母顺序排序哈希,Template::Toolkit会为您执行此操作。
use strict;
use warnings;
use Template;
my %hash = qw' a 1 b 2 c 3 ';
my $config = {
INCLUDE_PATH => '/search/path',
};
my $input = 'test.tt2';
my $template = Template->new( $config );
$template->process( $input, {
hash => \%hash,
})
[% FOREACH hash -%] [% key %] => [% value %] [% END %]
a => 1 b => 2 c => 3