如何在Perl中仅获取散列的一部分?

如何在Perl中仅获取散列的一部分?,perl,hash,Perl,Hash,有办法得到一个子散列吗?我需要使用散列切片吗 例如: %hash = ( a => 1, b => 2, c => 3 ); 我只要 %hash = ( a => 1, b => 2 ); 散列是一个无序的容器,但术语slice仅在有序容器中才有意义。也许可以考虑使用数组。否则,您可能只需删除所有不希望生成“子哈希”的元素。您可能需要组合所需密钥的列表: my @keys = qw(a b); 然后使用循环生成哈希: my %hash_slice; for(@

有办法得到一个子散列吗?我需要使用散列切片吗

例如:

%hash = ( a => 1, b => 2, c => 3 );
我只要

%hash = ( a => 1, b => 2 );

散列是一个无序的容器,但术语slice仅在有序容器中才有意义。也许可以考虑使用数组。否则,您可能只需删除所有不希望生成“子哈希”的元素。

您可能需要组合所需密钥的列表:

my @keys = qw(a b);
然后使用循环生成哈希:

my %hash_slice;
for(@keys) {
  $hash_slice{$_} = %hash{$_};
}
或:

(我的首选项是第二个,但您最喜欢的是哪一个。)

返回与键列表关联的值。要获取散列切片,请将sigil更改为@,并提供一个键列表(在本例中为
“a”
“b”
):

通常,您可以使用quote word运算符生成列表:

my @items = @hash{qw/a b/};
您还可以分配给一个哈希片,因此如果您想要一个包含另一个哈希子集的新哈希,您可以说

my %new_hash;
@new_hash{qw/a b/} = @hash{qw/a b/};
许多人将使用a而不是哈希切片:

my %new_hash = map { $_ => $hash{$_} } qw/a b/;
从Perl 5.20.0开始,如果使用%sigil而不是@sigil:

my %new_hash = %hash{qw/a b/};

太多的函数式编程让我首先想到
zip

安装了

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。)


避免
map
zip
解决方案产生的额外复制。(是的,在对哈希进行迭代时对其进行变异是安全的……只要变异只是删除最近迭代的一对。)

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,但没有其他内容)。

还有另一种方法:

my @keys = qw(a b);
my %hash = (a => 1, b => 2, c => 3);
my %hash_copy;
@hash_copy{@keys} = @hash{@keys};

perl 5.20中的新功能是使用最后一行中的%like返回键和值:

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!

由于没有逻辑上的“切片”,我怀疑与“地图”有关。在数组中,您可以基于索引执行此操作,但在散列中,其中的数据没有可靠的内部表示。您需要某种类型的限定符(regex?)来定义子哈希中应该包含的内容和不应该包含的内容。顺便说一句,您的哈希语法是错误的:使用圆括号“()”表示普通哈希,{}”表示匿名哈希引用。这让我更清楚了为什么“map”与哈希一起工作。谢谢斯拉里·沃尔,布莱恩·德福伊,还有……查斯。欧文斯…谢谢你这么全面的解释!您可能应该更清楚地说明,哈希片只包含值,而不是键/值对。如何使$hash->hslice(qw/ab/)比@{$hash}{qw/ab/}更好?或者这是一种如果我不得不问我太过不理解的情况吗?你应该有一个答案模板,这样“我使用驼鹿::”就在每个答案的开头查斯。欧文斯:那不是希利斯做的@{$hash}{…}返回值列表;hslice返回一个包含键和值的新哈希引用。请解释一下--
%keep=map+($)、qw(ab)?在Perl中,哈希片非常有用,并且完全受支持。要了解更多信息,请重新阅读。
%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;
my $hash = { a => 1, b => 2, c => 3, d => 4 };
$hash->hslice([qw/a b/]) # { a => 1, b => 2 };
my @keys = qw(a b);
my %hash = (a => 1, b => 2, c => 3);
my %hash_copy;
@hash_copy{@keys} = @hash{@keys};
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!