如何找到Perl多级哈希中的哪些键对应于给定值?

时间:2014-10-21 09:51:46

标签: perl hash

我有一个如下所示的数据结构:

my %hoh = (
    'T431567' => {
        machin => '01',
        bidule => '02',
        truc   => '03',
    },
    'T123456' => {
        machin => '97',
        bidule => '99',
        truc   => '69',
    },
    'T444444' => {
        machin => '12',
        bidule => '64',
        truc   => '78',
    },
);

我想搜索特定值的truc的各种值,并找到与该条目对应的顶级属性。例如,查找78的值,我想找到结果'T444444',因为$hoh{T444444}{truc}78

我该怎么办呢?

3 个答案:

答案 0 :(得分:5)

您可以使用grep

执行此操作
my @keys = grep { $hoh{$_}{truc} == 78 } keys %hoh;

请注意,如果散列中存在重复值,则可以返回多个键。另请注意,这不是特别有效,因为它必须搜索整个哈希。在大多数情况下它可能很好,但是如果哈希值非常大并且您可能需要针对它运行大量此类查询,则按照Sobrique的建议构建反向索引可能更有效:

my %trucs;
foreach my $part (keys %hoh) {
    my $val = $hoh{$part}{truc};
    push @{ $trucs{$val} }, $part;
}
my @keys = @{ $trucs{78} };

或者更一般地说:

my %index;
foreach my $part (keys %hoh) {
    my %data = %{ $hoh{$part} };
    foreach my $key (keys %data) {
        my $val = $data{$key};
        push @{ $index{$key}{$val} }, $part;
    }
}
my @keys = @{ $index{truc}{78} };

答案 1 :(得分:4)

无法使用该数据结构 - 没有您创建它,从值到键没有“向后”关系。

您有两种选择 - 运行搜索或创建'索引'。实际上,这些是相同的,只有一个保存结果。

my %index;
foreach my $key ( keys %hoh ) {
    my $truc = $hoh{$key}{'truc'};
    $index{$truc} = $key; 
}

注意 - 如果'truc'数字重复,它将不会做任何聪明的事情 - 它会覆盖。 (处理这个问题留给读者练习)。

答案 2 :(得分:2)

此解决方案与已发布的解决方案类似,但它使用each运算符以较少的代码行处理原始哈希,并且可能更快。

我只添加了转储输出,以便您可以看到构建的结构的形式。

use strict;
use warnings;

my %hoh = (
  T123456 => { bidule => '99',  machin => '97',  truc => '69' },
  T431567 => { bidule => '02',  machin => '01',  truc => '03' },
  T444444 => { bidule => '64',  machin => '12',  truc => '78' },
);

my %trucs;

while ( my ($key, $val) = each %hoh ) {
  next unless defined( my $truc = $val->{truc} );
  push @{ $trucs{$truc} }, $key ;
}

use Data::Dump;
dd \%trucs;
print "\n";

print "$_\n" for @{ $trucs{78} };

<强>输出

{ "03" => ["T431567"], "69" => ["T123456"], "78" => ["T444444"] }

T444444

如果你能保证答案是唯一的,即原始哈希中永远不会有多个元素具有truc条目的给定值,或者你是只对找到的最后一个感兴趣,那么你可以更整洁地写这个

my %trucs;

while ( my ($key, $val) = each %hoh ) {
  next unless defined( my $truc = $val->{truc} );
  $trucs{$truc} = $key ;
}

print $trucs{78}, "\n";

<强>输出

T444444

最简单的是,如果每个二级哈希中总是一个truc条目,保证其值是唯一的,那么这个将完成这项工作

my %trucs = map { $hoh{$_}{truc} => $_ } keys %hoh;

print $trucs{78}, "\n";

输出如上。