marc.garcia has asked for the wisdom of the Perl Monks concerning the following question:

Hey Monks, I am very new on perl but I like it a lot. Right now I am working on hashes, and I have a hash with multiple values for each key. I know that I can get the key for a certain value if it is the only value for that key. But how can I get the key if I only know one of its values? I know that I should put some code here, but I have no idea about how to write it Thanks for your help!!!!

Replies are listed 'Best First'.
Re: get a key for a value revisited
by targetsmart (Curate) on Mar 26, 2009 at 11:29 UTC
    perlintro
    perldsc
    Iterate through the hash
    use grep to find out the relevant match in values
    if you see a match in values, print the key

    How do I look up a hash element by value
    Get the Key corresponding to any given value


    Vivek
    -- In accordance with the prarabdha of each, the One whose function it is to ordain makes each to act. What will not happen will never happen, whatever effort one may put forth. And what will happen will not fail to happen, however much one may seek to prevent it. This is certain. The part of wisdom therefore is to stay quiet.
Re: get a key for a value revisited
by jethro (Monsignor) on Mar 26, 2009 at 11:53 UTC

    I assume you meant "I know that I can get the value for a certain key if it is the only value for that key".

    There are two methods to store more than one value per key: The simple one using string concatenation of the different values and a more sophisticated one where you store a link to an array as hash value. Here is how to do it with string concatenation:

    $hash{$key}= 'ape:b:cat' #stores the values 'ape','b' and 'cat' into t +he hash using ':' as delimiter #simple but the delimiter better not be in any values (you would have +to escape the delimiter which is messy) @values= split /:/,$hash{$key}; #get the values out of the string # checking for a specific value if ($hash{$key}=~/(^|:)$whatimlookingfor(:|$)/) { print "found it"; } $hash{$key}.= ':' . $anothervalue; #add another value (but if the hash + value was empty you have just added two values, an empty string and +$anothervalue. This is another disadvantage)

    The other method uses arrays to store the values. The structure is commonly called HashofArrays (HoA). The syntax is a bit more complicated, but it avoids some disadvantages of the first method

    $hash{$key}= ['ape','b','cat']; #stores the values 'ape','b' and 'cat' + into the hash @values= @{$hash{$key}}; #get all the values $value= $hash{$key}->[2]; #get the third value $value= $hash{$key}[2]; #get the third value, short form push @{$hash{$key}}, $anothervalue; #add a value

    As you can see the second method should be prefered, but if the syntax of a HashofArrays looks daunting to you or you have other compelling reasons, the first method can be used as well

Re: get a key for a value revisited
by leslie (Pilgrim) on Mar 26, 2009 at 12:31 UTC
    Hi,

    Values should be unique for each and every key while getting the hash key using value(For this cenario). Otherwise you may not get the key which you want.

    For example if you are having "apple" as a value in the h1 and h2 key. while getting the key using value(apple) you can't get your actual key which you want.

Re: get a key for a value revisited
by toolic (Bishop) on Mar 26, 2009 at 12:41 UTC
    It sounds like you want to organize your data as a Hash-of-Arrays structure, which can support multiple values for each key. To retrieve a key corresponding to a value, you could loop through the keys of the hash, then loop through the array elements for each key:
    use strict; use warnings; use Data::Dumper; # %data is an example Hash-of-Arrays structure # where the hash has 3 keys (a,b,c) and each # key has 3 values: my %data = ( a => [1..3], b => [4..6], c => [7..9], ); #print Dumper(\%data); print get_key(3), "\n"; print get_key(8), "\n"; print get_key(0), "\n"; sub get_key { my $value = shift; for my $key (keys %data) { for my $val (@{ $data{$key} }) { if ($val eq $value) { return $key; } } } return 'key not found'; } __END__ a c key not found
Re: get a key for a value revisited
by ig (Vicar) on Mar 28, 2009 at 22:26 UTC

    Another way to think about it is: if you are having to look up values to find keys you have built your hash the wrong way aroung. Hashes are good looking up keys to find values but not so good for looking up values to find keys. So, when you create your hash, swap the keys and values. Then your lookup will be easy.

    You can try something like the following: