如何在 Perl 中获取哈希的一部分?
Posted
技术标签:
【中文标题】如何在 Perl 中获取哈希的一部分?【英文标题】:How can I get a only part of a hash in Perl? 【发布时间】:2010-11-02 00:41:57 【问题描述】:有没有办法获得子哈希?我需要使用哈希切片吗?
例如:
%hash = ( a => 1, b => 2, c => 3 );
我只想要
%hash = ( a => 1, b => 2 );
【问题讨论】:
由于逻辑上没有什么可以“切片”的,我怀疑与“地图”有关。在数组中,您将基于索引来执行此操作,但在哈希中,其中的数据没有可靠的内部表示。您需要某种类型的限定符(正则表达式?)来定义什么应该进入 subhash,什么不应该。 顺便说一句,您的哈希语法错误:使用圆括号“()”表示普通哈希,“”表示匿名哈希引用。 【参考方案1】:Hash slices 返回与键列表关联的值。要获得哈希切片,您需要将 sigil 更改为 @ 并提供键列表(在本例中为 "a"
和 "b"
):
my @items = @hash"a", "b";
您通常可以使用引号单词运算符来生成列表:
my @items = @hashqw/a b/;
你也可以分配给一个散列片,所以如果你想要一个包含另一个散列子集的新散列,你可以说
my %new_hash;
@new_hashqw/a b/ = @hashqw/a b/;
很多人会使用map 代替哈希切片:
my %new_hash = map $_ => $hash$_ qw/a b/;
从 Perl 5.20.0 开始,如果使用 % sigil 而不是 @sigil,则可以一步获取键和值:
my %new_hash = %hashqw/a b/;
【讨论】:
这让我更清楚为什么“map”可以使用哈希值。谢谢 拉里·沃尔、布赖恩·德·福伊和……查斯。欧文斯...感谢您提供如此全面的解释! 您可能应该更清楚地说明哈希切片只有值,而不是键/值对。【参考方案2】:你可能想要组合一个你想要的键列表:
my @keys = qw(a b);
然后使用循环来做哈希:
my %hash_slice;
for(@keys)
$hash_slice$_ = %hash$_;
或者:
my %hash_slice = map $_ => $hash$_ @keys;
(我更喜欢第二个,但你喜欢哪个最好。)
【讨论】:
【参考方案3】:另一种方式:
my @keys = qw(a b);
my %hash = (a => 1, b => 2, c => 3);
my %hash_copy;
@hash_copy@keys = @hash@keys;
【讨论】:
【参考方案4】:太多的函数式编程让我首先想到zip
。
安装了List::MoreUtils,
use List::MoreUtils qw(zip);
%hash = qw(a 1 b 2 c 3);
@keys = qw(a b);
@values = @hash@keys;
%hash = zip @keys, @values;
不幸的是,List::MoreUtils 的zip
的原型抑制了
zip @keys, @hash@keys;
如果你真的想避免中间变量,你可以
zip @keys, @[@hash@keys];
或者只写你自己的zip
没有问题原型。 (这根本不需要 List::MoreUtils。)
sub zip
my $max = -1;
$max < $#$_and $max = $#$_ for @_;
map my $ix = $_; map $_->[$ix], @_; 0..$max;
%hash = zip \@keys, [@hash@keys];
如果你要就地变异,
%hash = qw(a 1 b 2 c 3);
%keep = map +($_ => 1), qw(a b);
$keep$a or delete $hash$a while ($a, $b) = each %hash;
避免map
和zip
解决方案产生的额外复制。 (是的,在迭代哈希时对其进行变异是安全的……只要变异只删除最近迭代的对。)
【讨论】:
请解释一下 --%keep = map +($_ => 1), qw(a b);
?【参考方案5】:
FWIW,我在这里使用 Moose::Autobox:
my $hash = a => 1, b => 2, c => 3, d => 4 ;
$hash->hslice([qw/a b/]) # a => 1, b => 2 ;
在现实生活中,我使用它从表单提交中提取“用户名”和“密码”,并将其传递给 Catalyst 的 $c->authenticate
(在我的情况下,它期望包含用户名和密码的 hashref,但没有否则)。
【讨论】:
$hash->hslice(qw/a b/) 比 @$hashqw/a b/ 好多少?或者这是其中一种情况,如果我不得不问,我就太远了,无法理解? 您应该有一个答案模板,以便“我使用 Moose::”在每个答案的开头。 :) 查斯。 Owens:这不是 hslice 所做的。 @$hash... 返回值列表; hslice 返回一个包含键和值的新哈希引用。【参考方案6】:perl 5.20 中的新功能是哈希切片返回键和值,使用 % 就像这里的最后一行一样:
my %population = ('Norway',5000000,'Sweden',9600000,'Denmark',5500000);
my @slice_values = @population'Norway','Sweden'; # all perls can do this
my %slice_hash = %population'Norway','Sweden'; # perl >= 5.20 can do this!
【讨论】:
【参考方案7】:散列是一个无序容器,但术语切片仅在有序容器方面才真正有意义。也许考虑使用数组。否则,您可能只需要删除所有不想产生“子哈希”的元素。
【讨论】:
在 Perl 中,散列切片很有用并且得到完全支持。要了解更多信息,请重新阅读the 'Slices' section in perldata。以上是关于如何在 Perl 中获取哈希的一部分?的主要内容,如果未能解决你的问题,请参考以下文章