我有一个如下所示的数据结构:
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
。
我该怎么办呢?
答案 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";
输出如上。