J'ai un hachage simple et je voudrais renvoyer la clé $ basée sur les critères de valeur $. C'est-à-dire que pour la ligne 14, de quel code aurais-je besoin pour renvoyer la clé $ où la valeur de $ est "jaune"?
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? ";
grep
est le bon outil pour ce travail:
my @all_matches = grep { $fruit{$_} eq 'yellow' } keys %fruit;
print("$_ ") foreach @matching_keys;
my ($any_match) = grep { $fruit{$_} eq 'yellow' } keys %fruit;
Je ne suis pas sûr que ce soit facile à faire efficacement avec un hash à sens unique. L'intérêt d'un hachage est de convertir la clé en une valeur (ou la position de la valeur si vous regardez sous les couvertures). Vous pouvez effectuer une recherche exhaustive sur toutes les valeurs, en collectant les clés au fur et à mesure, mais ce n'est pas aussi efficace qu'une recherche de hachage.
Pour aller dans le sens contraire efficacement,, vous pouvez envisager un hachage bidirectionnel, quelque chose comme:
%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";
sub find_key {
my ( $h, $value ) = @_;
while ( my ( $k, $v ) = each %$h ) {
return $k if $v eq $value;
}
return;
}
Pour que vous puissiez l'appeler ainsi:
find_key( \%fruit, 'yellow' );
Certaines de vos valeurs étant des tableaux, vous devez vérifier cela.
Appeler:
my @fruit = getfruit(\%fruit, $colour);
Le sous-programme:
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;
}
Utiliser une expression rationnelle à la place de eq est optionnel, gardez toujours le même cas, car Yellow
et yellow
sont considérés comme des clés différentes.
Je remarque que votre exemple contient des références à des tableaux anonymes. Je ferais donc une longue boucle 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";