2009-06-11 75 views
17

有没有办法获得子哈希?我需要使用散列片吗?如何在Perl中获得散列的唯一部分?

例如:

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

我只想

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

由于没有什么逻辑上“片”我怀疑与'地图'有关。 在一个数组中,你会根据索引来做它,但是在哈希中没有可靠的内部数据表示。你需要一些类型的限定符(正则表达式?)来定义应该进入subhash的内容以及不应该进入的内容。 – 2009-06-11 03:59:53

+3

顺便说一句,你的哈希语法是错误的:使用圆括号“()”为一个普通的散列,“{}”为匿名散列引用。 – trendels 2009-06-11 07:35:49

回答

46

Hash slices返回与键列表关联的值。为了让你改变印记为@散片,并提供键的列表(在这种情况下"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/}; 
+0

这使得为什么“地图”工作w /哈希清晰一点给我。谢谢 – 2009-06-11 04:15:11

+0

拉里沃尔,布莱恩福伊和查斯。欧文斯......谢谢你这个非常全面的解释! – bernie 2009-06-11 04:19:20

-3

散列是一个无序的容器,但片这一术语才真正有意义有序容器方面。也许看看使用数组。否则,你可能只需要删除你不想产生你的'子哈希'的所有元素。

+0

在Perl中,散列片很有用,并且完全支持。要了解更多重新阅读 [_perldata_中的'切片'部分](http://perldoc.perl.org/perldata.html#Slices)。 – 2015-11-19 13:36:50

9

你可能想组装你想要的密钥列表:

my @keys = qw(a b); 

然后使用一个循环,使哈希:

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

或者:

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

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

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; 

不幸的是,名单的原型:: 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解决方案承担。 (是的,变异的散列当你迭代它是安全的......只要突变只删除最近反复对)

3

FWIW,我用麋:: Autobox这里:

my $hash = { a => 1, b => 2, c => 3, d => 4 }; 
$hash->hslice([qw/a b/]) # { a => 1, b => 2 }; 

在现实生活中,我使用它从表单提交中提取“用户名”和“密码”,并将其传递给Catalyst的$c->authenticate(在我的情况下,期望的是包含用户名和密码的hashref,但没有其他)。

6

还有一种方法:

my @keys = qw(a b); 
my %hash = (a => 1, b => 2, c => 3); 
my %hash_copy; 
@hash_copy{@keys} = @hash{@keys}; 
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!