排序的键/值对数组到排序的键和哈希数组

发布于 2024-10-30 19:19:05 字数 1560 浏览 5 评论 0原文

我正在开发一个 Catalyst 应用程序,它使用 Template::Toolkit 作为模板引擎。一个页面需要一系列相同的输入元素。它们可以从数组中获取,但我需要元素的排序顺序和描述性标签。

为了获得排序顺序,我将使用数组。为了存储每个键的附加值,散列是完美的。如何在 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 个项目,不够长,无法执行一些数据库操作)。

I am developing a Catalyst app which uses Template::Toolkit as template engine. One page needs a list of equal input elements. They can be taken from an array but I need both sort order and a descriptive label for the element.

For having a sort order I would use an array. For storing an additional value per key a hash is perfect. How to combine both in TT? I could use both things but that seems ugly and can cause mistakes when changing the fields.

However, I prefer doing this in TT because both the descriptions and the order of form elements is a front-end thing.

This is how I would do it in pure 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 $_]";
}

Outputs:

=== 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]

This is what I write in my template:

[%
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 %]

However, it is really ugly to have the same information (list of fields) twice. I want to avoid editing the list twice and with a longer list of fields it gets really annoying (about 20 items, not long enough to do some database stuff).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

瀞厅☆埖开 2024-11-06 19:19:05

令人惊奇的是人们如何将简单的事情复杂化!

您不需要 @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;

编写排序的比较函数留作练习:)

It's amazing how people complicate easy stuff!

You don't need the @fields array. Please read the perldoc about keys, values and sort.

# untested sketch
my %description = ( prop23 => "foo", prop24 => "bar" );
foreach my $key(sort (keys %description)) {
    print $key, " is: ", $description{$key}, "\n";   # or whatever
}

Addendum: Regarding the order of keys, just do the following:

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;

Writing the comparison function for sort is left as an exercise :)

夏日落 2024-11-06 19:19:05

您可能对 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;

编辑2:我已经尝试过,它实际上有效:

#!/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 %]

You might be interested in Tie::IxHash

It is a "hash" that keeps the order in which you add keys (value updates do not affect sorting).

EDIT: A brief example:

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: I've tried it out, and it actually works:

#!/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 %]
超可爱的懒熊 2024-11-06 19:19:05

如果您需要排序和多条信息,那么您应该考虑哈希引用数组。

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";
}

如果复杂性增加远远超出此范围,您可能会考虑用真实对象替换哈希引用。

在 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 %]

If you need ordering and multiple pieces of information then you should consider an array of hash references.

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";
}

If the complexity increases much beyond this, you might consider replacing the hashrefs with real objects.

And, in TT, it looks like this:

[%-
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 %]
楠木可依 2024-11-06 19:19:05

实际上,如果您希望哈希按键按字母顺序排序,Template::Toolkit 可以为您做到这一点。

test.pl

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,
})

test.tt2

[% FOREACH hash -%]
[% key %] => [% value %]
[% END %]

输出

a => 1
b => 2
c => 3

Actually if you want your hash alphabetically sorted by key, Template::Toolkit does that for you.

test.pl

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,
})

test.tt2

[% FOREACH hash -%]
[% key %] => [% value %]
[% END %]

output

a => 1
b => 2
c => 3
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文