【问题标题】:Simple hash search by value按值进行简单哈希搜索
【发布时间】:2012-01-03 12:31:09
【问题描述】:

我有一个简单的散列,并希望根据 $value 条件返回 $key。也就是说,对于第 14 行,我需要什么代码来返回 $value 为“黄色”的 $key?

1  #!/usr/bin/perl
2
3  # This program creates a hash then
4  # prints out what is in the hash
5
6  %fruit = (
7   'apple' => ['red','green'],
8   'kiwi' => 'green',
9   'banana' => 'yellow',
10  );
11
12 print "The apple is @{$fruit{apple}}.\n";
13 print "The kiwi is $fruit{kiwi}.\n";
14 print "What is yellow? ";

【问题讨论】:

    标签: perl search hash grep


    【解决方案1】:

    grep 是这项工作的正确工具:

    my @all_matches = grep { $fruit{$_} eq 'yellow' } keys %fruit;
    print("$_ ") foreach @matching_keys;
    
    my ($any_match) = grep { $fruit{$_} eq 'yellow' } keys %fruit;
    

    【讨论】:

    • print "$_ " foreach @matching_keys 最好写成print "@matching_keys",没有尾随空格作为奖励。此外, codaddict 是正确的,grep 不会对数组引用的值起作用。
    【解决方案2】:

    我不太确定使用单向哈希很容易有效地做到这一点。散列的全部意义在于将键转换为值(或者如果您在幕后查看值的位置)。您可以对所有值进行详尽的搜索,边走边收集键,但这不如哈希查找高效。

    为了有效地走另一条路,您可能需要考虑双向哈希,例如:

    %fruit = (
        'apple' => ['red','green'],
        'kiwi' => 'green',
        'banana' => 'yellow',
    );
    %antifruit = (
        'red' => 'apple',
        'green' => ['apple','kiwi'],
        'yellow' => 'banana',
    );
    print "The apple is @{$fruit{'apple'}}.\n";
    print "The kiwi is $fruit{'kiwi'}.\n";
    print "A yellow thing is $antifruit{'yellow'}.\n";
    

    【讨论】:

      【解决方案3】:
      sub find_key { 
          my ( $h, $value ) = @_;
          while ( my ( $k, $v ) = each %$h ) { 
              return $k if $v eq $value;
          }
          return;
      }
      

      所以你可以这样称呼它:

      find_key( \%fruit, 'yellow' );
      

      【讨论】:

        【解决方案4】:

        由于您的某些值是数组,因此您需要对其进行检查。

        来电:

        my @fruit = getfruit(\%fruit, $colour);
        

        子程序:

        sub getfruit {
            my ($fruit, $col) = @_;
            my @result;
            for my $key (keys %$fruit) {
                if (ref $fruit->{$key} eq 'ARRAY') {
                    for (@{$fruit->{$key}}) {
                        push @result, $key if /^$col$/i;
                    }
                } else {
                    push @result, $key if $fruit->{$key} =~ /^$col$/i;
                }
            }
            return @result;
        }
        

        使用正则表达式代替 eq 是可选的,请注意保持大小写相同,因为 Yellowyellow 被视为不同的键。

        【讨论】:

          【解决方案5】:

          我注意到您的示例引用了匿名数组,所以我只会做一个冗长的 foreach/if 循环:

          my %fruit = (
            'apple' => ['red','green'],
            'kiwi' => 'green',
            'banana' => 'yellow',
          );
          
          print "The apple is @{$fruit{apple}}.\n";
          print "The kiwi is $fruit{kiwi}.\n";
          print "What is yellow? ";
          
          my $ele;
          my $search = 'yellow';
          my @match = ();
          
          foreach $ele (keys(%fruit)) {
              if(ref($fruit{$ele}) eq 'ARRAY' and
                  grep { $_ eq $search } @{ $fruit{$ele} }) {
                  push(@match, $ele);
              } elsif(!ref($fruit{$ele}) and $fruit{$ele} eq $search) {
                  push(@match, $ele);
              }
          }
          print join(", ", @match) . "\n";
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-09-08
            • 2016-06-27
            • 2017-02-15
            • 2010-10-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-10-22
            相关资源
            最近更新 更多