2011-11-22 124 views
17

我有一个简单的哈希,并希望根据$ value条件返回$ key。也就是说,对于第14行,我需要什么代码才能返回$ key为“黄色”的$ 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? "; 

回答

19

grep是这个职位的最佳工具:

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

my ($any_match) = grep { $fruit{$_} eq 'yellow' } keys %fruit; 
+1

并非所有值都是标量。 – codaddict

+3

'print“$ _”foreach @ matching_keys'更好地写成'print'@matching_keys“',没有后面的空格作为奖励。此外,codaddict是正确的,grep不会在数组引用的值上工作。 – TLP

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"; 
1
sub find_key { 
    my ($h, $value) = @_; 
    while (my ($k, $v) = each %$h) { 
     return $k if $v eq $value; 
    } 
    return; 
} 

所以,你可以把它像这样:

find_key(\%fruit, 'yellow'); 
0

我注意到你的榜样有匿名数组引用,所以我只想做一个长篇大论的foreach /如果循环:

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"; 
1

由于一些你的价值观是数组,你需要检查这一点。

呼叫:

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

使用正则表达式,而不是情商是可选的,只要留心保持相同的情况下,因为Yellowyellow是考虑了不同的键。