2011-11-22 19 views
17

Tengo un hash simple y me gustaría devolver la clave $ en función de los criterios de $ value. Es decir, para la línea 14, ¿qué código necesitaría para devolver la clave $ donde el valor $ es "amarillo"?Búsqueda de hash simple por valor

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

Respuesta

19

grep es la herramienta adecuada para este trabajo:

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

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

No todos los valores son escalares. – codaddict

+3

'print" $ _ "foreach @ matching_keys' mejor escrito como' print '@matching_keys "', sin espacio final como bonificación. Además, codaddict es correcto, grep no funcionará en los valores que son referencias de matriz. – TLP

2

No estoy tan seguro de que sea fácil de hacer eficientemente con un hash de un solo sentido. El objetivo de un hash es convertir la clave en un valor (o posición del valor si está buscando debajo de las cubiertas). Puede hacer una búsqueda exhaustiva de todos los valores, recopilando las claves sobre la marcha, pero eso no es tan eficiente como una búsqueda hash.

Con el fin de ir a otro lado eficiente, es posible que desee considerar un hash de dos vías, algo así como:

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

así se podría llamar así:

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

Tomo nota de su ejemplo tiene referencias a arrays anónimos, por lo que sólo haría un largo aliento foreach/si el rizo:

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

Dado que algunos de sus valores son matrices, es necesario comprobar para eso.

Calling:

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

El subprograma:

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

Usando una expresión regular en lugar de la ecuación es opcional, acaba de ser conscientes de mantener el mismo caso, ya que Yellow y yellow son considerado claves diferentes.

Cuestiones relacionadas