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

时间:2009-06-11 03:49:08

标签: perl hash

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

例如:

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

我只想要

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

7 个答案:

答案 0 :(得分:51)

Hash slices返回与键列表关联的值。要获取哈希切片,请将sigil更改为@并提供密钥列表(在本例中为"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开始,如果使用%sigil而不是@sigil,则可以一步获取键和值:

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

答案 1 :(得分:9)

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

my @keys = qw(a b);

然后使用循环来制作哈希:

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

或者:

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

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

答案 2 :(得分:6)

另一种方式:

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

答案 3 :(得分: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;

避免mapzip解决方案产生的额外复制。 (是的,在迭代它时改变哈希是安全的......只要突变只删除最近迭代的对。)

答案 4 :(得分: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(在我的情况下,它需要包含用户名和密码的hashref,但没有别的。)

答案 5 :(得分:2)

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!

答案 6 :(得分:-3)

散列是一个无序容器,但术语切片只对有序容器有意义。也许考虑使用数组。否则,您可能只需要删除所有不想产生“子哈希”的元素。