简体   繁体   English

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

[英]How can I find which keys in a Perl multi-level hash correspond to a given value?

I have a data structure which looks like this: 我有一个看起来像这样的数据结构:

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

I want to search the various values of truc for a particular value and find the top-level attribute which corresponds to that entry. 我想搜索特定值的truc的各种值,并找到与该条目相对应的顶级属性。 For example, looking for a value of 78 , I want to find the result 'T444444' , because $hoh{T444444}{truc} is 78 . 例如,查找值为78 ,我想查找结果'T444444' ,因为$hoh{T444444}{truc}78

How can I do this, please? 请问我该怎么做?

You can do this with grep : 您可以使用grep做到这一点:

my @keys = grep { $hoh{$_}{truc} == 78 } keys %hoh;

Note that this can return more than one key, if there are duplicate values in the hash. 请注意,如果哈希中存在重复的值,则此方法可以返回多个键。 Also note that this is not particularly efficient, since it has to search the entire hash. 还要注意,这并不是特别有效,因为它必须搜索整个哈希。 In most cases it's probably fine, but if the hash can be very large and you may need to run lots of such queries against it, it may be more efficient to build a reverse index as suggested by Sobrique: 在大多数情况下,它可能很好,但是如果散列可能非常大,并且您可能需要对其进行大量此类查询,那么如Sobrique所建议的那样,建立反向索引可能会更有效:

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

or, more generally: 或者,更一般而言:

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} };

Can't with that data structure as is - There is no 'backwards' relationship from value to key without you creating it. 无法按原样使用该数据结构-如果不创建值,则从值到键就没有“反向”关系。

You've two options - run a search, or create an 'index'. 您有两个选择-运行搜索或创建“索引”。 Practically speaking, these are the same, just one saves the results. 实际上,这些是相同的,只是保存一个结果。

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

Note - won't do anything clever if the 'truc' numbers are duplicated - it'll overwrite. 注意-如果重复'truc'数字不会做任何聪明的事-它会覆盖。 (Handling this is left as an exercise to the reader). (处理此操作留给读者练习)。

This solution is similar to those already posted, but it uses the each operator to process the original hash in fewer lines of code, and probably more quickly. 该解决方案类似于已经发布的解决方案,但是它使用each运算符以更少的代码行(可能更快)来处理原始哈希。

I have added the dump output only so that you can see the form of the structure that is built. 我仅添加了转储输出,以便您可以看到所构建结构的形式。

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} };

output 输出

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

T444444

If you can guarantee that the answer is unique, ie that there is never more than one element of the original hash that has a given value for the truc entry, or you are interested only in the last one found, then you can write this still more neatly 如果您可以保证答案是唯一的,即原始哈希中不超过一个给定truc条目的给定值的元素,或者您只对找到的最后一个感兴趣,那么您仍然可以编写此答案更加整齐

my %trucs;

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

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

output 输出

T444444

Simplest of all, if there is always a truc entry in each second-level hash, and its values is guaranteed to be unique, then this will do the job 最简单的是,如果每个第二级哈希中始终有一个truc条目, 并且其值被保证是唯一的,那么这将完成工作

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

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

with the output as above. 与上面的输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM