按值进行简单哈希搜索

19

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

21

grep 是处理这个任务的正确工具:

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

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

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' );

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

使用正则表达式而不是 eq 是可选的,只要注意保持相同的大小写,因为 Yellowyellow 被认为是不同的键。


0

我注意到你的例子中有匿名数组的引用,所以我会使用冗长的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";

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接