在Perl中双哈希值

3

使用哈希表时,Perl 有一个非常方便的 values 关键字,可以处理哈希表的值。

假设我有一个双层哈希表,也就是像这样创建的:

my %dh = map { {$_->{id1}}{$_->{id2}} => $_ } @arr;

然后,values %dh 返回一个哈希数组。要访问这些值,我需要像这样做:

for my $key1 (keys %dh) {
    for my $val (values %{ $dh{$key1} }) {
        # stuff...
    }
}

有没有更好的方法来实现这个,避免使用for循环?类似于values %{ values %dh }。另外,很抱歉语法比较差,我对Perl还不是很熟悉。

“map”和“keys”我猜应该是,但现在我没有时间构建测试用例。 - Quentin
1个回答

5

您可以再次使用map来提取它。不过,不要有任何幻想——它仍然在循环。但这样可能更加优雅:

for my $val ( map { values %$_ } values %dh ) {
    #do stuff
}

这基本上做着同样的事情 - 它正在扁平化你的哈希表 - 从 %dh 获取 values - 这将是一个哈希引用列表 - 然后将这些哈希引用中的 values 取出。(我认为这应该可以做到,但没有测试数据,无法确定)。

请注意 - 从 values 返回的顺序是未定义的,因此您会以随机的方式获得它们。如果您愿意,可以通过 keys (和可能的 sort) 控制排序顺序。

map 所做的就是简单地评估一段代码块,并将结果返回为列表。这就是为什么 map { $_ => 1 } qw ( one two three ) 起作用 - 它实际上返回一对值,当您将其分配给哈希时,它被视为键值对。

use Data::Dumper;

my @stuff = map { $_ => 1 } qw ( one two three );
print Dumper \@stuff;
my %hash = map { $_ => 1 } qw ( one two three ); 
print Dumper \%hash;

所以 - 这里map函数返回了2个值,你可以这样写:could
my @stuff = map { $_,  1 } qw ( one two three );

当然,=>实际上只是一个逗号(带有一些引用附加功能)。

因此,在解除对数组的引用时,您可以执行相同操作- valuesmap中的每个元素返回一组值。

为了清晰起见:

use Data::Dumper;
my @stuff = ( [ 1, 2, 3 ], [4, 5, 6], [7, 8, 9] );
print Dumper \@stuff;
my @newstuff = map { @$_ } @stuff; 
print Dumper \@newstuff;

这其实做的是相同的事情 - 遍历@stuff中每个哈希引用(因为这就是perl中实现多维数组的方式),然后“解包”它们并返回结果。


2
这里的重点是,您可以从传递给 map 的代码块返回多个值,并且它们将被展平为来自 map 的一个值流。 - Jonas Berlin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接