Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

Getting Keys of Hash from Values

by jesuashok (Curate)
on Nov 16, 2005 at 20:54 UTC ( #509187=perlquestion: print w/replies, xml ) Need Help??
jesuashok has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,

Let me brief the basics of hash.

keys %hash; will return the keys available in Hash.

values %hash; will return the values available in Hash.

But Recently I met an Issue as follows :-

my %param; foreach my $values ( sort values %user_details ) { $param{user_name} = $values; }

I will use the Above sorted user names to display in the web screen.

But suddenly I had a requirement like to get the keys of hash by using the hash values.

Is there a way to get the key of a hash using its values.

Because as per my understanding the keys of Hash can not be duplicate, Even if it is so there is no meaning in having that

$hash{1} = 'One'; $hash{1} = 'one'; # No use

can any one have Idea in getting this work ?

"Keep pouring your ideas"

2005-11-17 Retitled by Arunbear, as per consideration
Original title: 'Getting Keys of Hash'

Replies are listed 'Best First'.
Re: Getting Keys of Hash from Values
by ikegami (Pope) on Nov 16, 2005 at 21:07 UTC
    Like this?
    my %hash = ( apple => 'red', banana => 'yellow', orange => 'orange', lemon => 'yellow', ); my $value = 'yellow'; my @matching_keys = grep { $hash{$_} eq $value } keys %hash; print("$_\n") foreach @matching_keys;
Re: Getting Keys of Hash from Values
by duff (Vicar) on Nov 16, 2005 at 21:10 UTC

    I think you want something like this:

    my @keys = grep { $hash{$_} eq $value } keys %hash;
    That iterates over all of the keys of %hash and if any value in the hash is equal to the value we're interested in, then the expression evaluates to a true value and so the key gets put into the @keys array.
Re: Getting Keys of Hash from Values
by davido (Archbishop) on Nov 16, 2005 at 21:14 UTC

    If you're just doing it once, use ikegami's approach. If you're doing it many times (where the term 'many' is intentionally vague) you may benefit from maintaining two hashes; one forward-lookup and one reverse-lookup, if that makes sense.

    Bear in mind, however, that in a hash, while the keys are guaranteed to be unique, there is no guarantee that the values are unique. So there's a possibility that 'yellow' as a value could occur several times, each under different unique keys. This must be dealt with somehow when doing reverse-lookups. One way is to just make sure you "don't do that" (don't create hash entries that have equal values). And it happens that maintaining a reverse-lookup hash is an excellent way of keeping track of two-way uniqueness. ...but this is just a tangent...


Re: Getting Keys of Hash from Values
by tmoertel (Chaplain) on Nov 16, 2005 at 21:20 UTC
    On the subject of inverting hashes, you can invert a hash via reverse like so:
    my %hash = ( a => 1, b => 2, c => 3 ); my %inverted_hash = reverse %hash;
    To see the results, we can use Data::Dumper:
    use Data::Dumper; print Dumper(\(%hash, %inverted_hash)); # Output: # $VAR1 = { # 'c' => 3, # 'a' => 1, # 'b' => 2 # }; # $VAR2 = { # '1' => 'a', # '3' => 'c', # '2' => 'b' # };
    As you note, however, not all hashes have one-to-one mappings to their inverted forms. In such a case the inverted form will have fewer key-value pairs than the original hash:
    %hash = ( a => 1, b => 2, c => 2 ); %inverted_hash = reverse %hash; print Dumper(\(%hash, %inverted_hash)); # Output: # $VAR1 = { # 'c' => 2, # 'a' => 1, # 'b' => 2 # }; # $VAR2 = { # '1' => 'a', # '2' => 'c' # };
    You can use this property to test whether you have lost information during inversion:
    print "keys were lost during inversion\n" if keys %inverted_hash < keys %hash;


Re: Getting Keys of Hash from Values
by gjb (Vicar) on Nov 16, 2005 at 21:43 UTC

    You could have a look at Tie::Hash::TwoWay, however, be sure to read the 'pecularities' listed.

    Hope this helps, -gjb-

Re: Getting Keys of Hash from Values
by GrandFather (Sage) on Nov 16, 2005 at 21:14 UTC

    It's not clear from your description just what you want to try an achieve. Could you show us sample contents of %user_details and what you expect %param to contain following the loop?

    As shown %param will contain one value (the "largest" according to the sort criteria) with the key user_name. I doubt that that is what you want.

    Note also that the sort is futile in this case. It has no useful effect on the behaviour of the loop nor on how things are stored in %param.

    DWIM is Perl's answer to Gödel
Re: Getting Keys of Hash from Values
by injunjoel (Priest) on Nov 16, 2005 at 23:13 UTC
    I was just wondering why you don't use keys to begin with?
    Untested Example
    my %param; foreach ( sort { $user_details{$a} cmp $user_details{$b} } keys %user_ +details ){ #this next line will clobber $param{user_name} each time through. #$param{user_name} = $user_details{$_}; #do your stuff. print "the key is $_\n"; print "the value is $user_details{$_}\n"; }
    Just a thought.

    "I do not feel obliged to believe that the same God who endowed us with sense, reason and intellect has intended us to forego their use." -Galileo
Re: Getting Keys of Hash from Values
by ptum (Priest) on Nov 16, 2005 at 21:13 UTC
    Or how 'bout this?
    #!/usr/local/bin/perl -w use strict; my %hash = ( apple => 'red', banana => 'yellow', orange => 'orange', lemon => 'yellow', ); my $value = 'yellow'; my %newhash = reverse %hash; print $newhash{$value}, "\n";

      That doesn't return all the keys if the values are not unique. According to the output either lemons or bananas aren't yellow.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://509187]
Approved by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (5)
As of 2017-10-19 02:09 GMT
Find Nodes?
    Voting Booth?
    My fridge is mostly full of:

    Results (251 votes). Check out past polls.