按值进行简单哈希搜索

发布于 2024-12-17 11:33:24 字数 439 浏览 0 评论 0原文

我有一个简单的散列,并且想根据 $value 标准返回 $key 。也就是说,对于第 14 行,我需要什么代码来返回 $key(其中 $value 为“黄色”)?

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

I have a simple hash, and would like to return the $key based on $value criteria. That is, for line 14, what code would I need to return the $key where the $value is "yellow"?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

一杆小烟枪 2024-12-24 11:33:24

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

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

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

grep is the right tool for this job:

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

my ($any_match) = grep { $fruit{$_} eq 'yellow' } keys %fruit;
巴黎夜雨 2024-12-24 11:33:24

我不太确定使用单向哈希是否可以轻松有效地完成这一任务。哈希的全部要点是将键转换为值(如果您正在查看幕后,则将其转换为值的位置)。您可以对所有值进行详尽的搜索,同时收集键,但这不如哈希查找那么有效。

为了有效地采用另一种方式,您可能需要考虑双向哈希,例如:

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

I'm not so sure that's easy to do efficiently with a one-way hash. The whole point of a hash is to convert the key into a value (or position of the value if you're looking under the covers). You can do an exhaustive search over all the values, collecting the keys as you go but that's not as efficient as a hash lookup.

In order to go the other way efficiently, you might want to consider a two-way hash, something like:

%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";
就是爱搞怪 2024-12-24 11:33:24
sub find_key { 
    my ( $h, $value ) = @_;
    while ( my ( $k, $v ) = each %$h ) { 
        return $k if $v eq $value;
    }
    return;
}

所以你可以这样称呼它:

find_key( \%fruit, 'yellow' );
sub find_key { 
    my ( $h, $value ) = @_;
    while ( my ( $k, $v ) = each %$h ) { 
        return $k if $v eq $value;
    }
    return;
}

So you could call it like so:

find_key( \%fruit, 'yellow' );
香橙ぽ 2024-12-24 11:33:24

由于某些值是数组,因此您需要检查这一点。

调用:

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 是可选的,只需注意保持相同的大小写,因为 Yellow黄色被认为是不同的键。

Since some of your values are arrays, you need to check for that.

Calling:

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

The subroutine:

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

Using a regex instead of eq is optional, just be mindful of keeping the same case, since Yellow and yellow are considered different keys.

倾城泪 2024-12-24 11:33:24

我注意到你的例子引用了匿名数组,所以我只会做一个冗长的 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";

I note your example has references to anonymous arrays, so I would just do a long winded foreach/if loop:

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";
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文