如何在 Perl 中获取哈希的唯一部分?

问题描述 投票:0回答:7

有没有办法获得子哈希?我需要使用哈希片吗?

例如:

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

我只要

%hash = ( a => 1, b => 2 );
perl hash
7个回答
63
投票

哈希切片返回与键列表关联的值。要获得哈希切片,请将印记更改为 @ 并提供键列表(在本例中为

"a"
"b"
):

my @items = @hash{"a", "b"};

通常您可以使用引号词运算符来生成列表:

my @items = @hash{qw/a b/};

您还可以分配给哈希切片,因此如果您想要一个包含另一个哈希的子集的新哈希,您可以说

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

很多人会使用 map 而不是哈希切片:

my %new_hash = map { $_ => $hash{$_} } qw/a b/;

从 Perl 5.20.0 开始,如果使用 % 印记而不是 @ 印记,您可以一步获取键和值:

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

9
投票

您可能想要组合您想要的键列表:

my @keys = qw(a b);

然后使用循环来生成哈希:

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

或者:

my %hash_slice = map { $_ => $hash{$_} } @keys;

(我的偏好是第二个,但你喜欢哪个最好。)


6
投票

还有另一种方式:

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

3
投票

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
(在我的例子中,它期望包含用户名和密码的哈希引用,但没有其他内容) .


3
投票

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

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
解决方案产生的额外复制。 (是的,在迭代哈希时对其进行变异是安全的......只要变异仅删除最近迭代的对。)


2
投票

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!

-3
投票

哈希是无序容器,但术语切片只有在有序容器方面才真正有意义。也许考虑使用数组。否则,您可能只需要删除所有您不想生成“子哈希”的元素即可。

© www.soinside.com 2019 - 2024. All rights reserved.