Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

getting hash key with value

by sovixi (Novice)
on Apr 16, 2008 at 00:10 UTC ( #680691=perlquestion: print w/replies, xml ) Need Help??
sovixi has asked for the wisdom of the Perl Monks concerning the following question:

O mighty Monks, Is there any chance I can find hash key by just giving it the associated value? (all data in the hash is unique: each key corresponds to different value) Thank you.

Replies are listed 'Best First'.
Re: getting hash key with value
by Fletch (Chancellor) on Apr 16, 2008 at 00:17 UTC

    Given the constraint that the values are distinct, just make a reverse mapping and use that. my %vals_to_keys; @vals_to_keys{ values %src } = keys %src;

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      Thanks a lot!!!
Re: getting hash key with value
by tachyon-II (Chaplain) on Apr 16, 2008 at 00:23 UTC

    This will only work is the values are unique but all you need to do is create a reversed hash lookup table and use that:

    my %h = qw( 1 2 3 4 5 6 ); my %rev_h = reverse %h; use Data::Dumper; print Data::Dumper::Dumper(\%h,\%rev_h); __DATA__ $VAR1 = { '1' => '2', '3' => '4', '5' => '6' }; $VAR2 = { '6' => '5', '4' => '3', '2' => '1' };

    If you can't guarantee the values are unique then you have to iterate. Use grep:

    my @keys = grep{ $hash{$_} eq $find } keys %hash;
Re: getting hash key with value
by ysth (Canon) on Apr 16, 2008 at 02:07 UTC
Re: getting hash key with value
by GrandFather (Sage) on Apr 16, 2008 at 00:20 UTC

    Create a reverse lookup hash. Consider:

    use strict; use warnings; my %hash = (x => 1, y => 2, z => 3); my %rhash; @rhash{values %hash} = keys %hash; print $rhash{1};



    Perl is environmentally friendly - it saves trees
Re: getting hash key with value
by oko1 (Deacon) on Apr 16, 2008 at 02:11 UTC

    In my experience, whenever I find myself with a need/question of this sort, it usually means that my data structure was incorrectly designed from the start. Often, adding another variable - an array, or a second hash, or (if the keys and the values are easily told apart) additional members in the original hash - during the data collection/aggregation part of the process takes care of the problem, and does not require doubling the space.

    If for some reason you really do need a one-to-one correspondence - that is, you have two sets of data in which you must be able to look up a corresponding member for every element - then a simple hash is probably not what you want.

    Human history becomes more and more a race between education and catastrophe. -- HG Wells
Re: getting hash key with value
by sundialsvc4 (Abbot) on Apr 16, 2008 at 01:51 UTC

    It all depends on how many thousand entries are in your hash to begin with. If the number is reasonable and you don't do it too often, it just might be simplest and quickest (if slightly aromatic...) to just iterate through the hash sequentially. In other words, you might get away with it.

    Otherwise, you're going to have to create a reverse-hash, and each slot in that reverse-hash can contain either a single value, or an array-reference containing a list of values.

    The tradeoff, as usual, is the usual one: speed versus space. By building a reverse-hash you just at-least-doubled your storage requirement... but it's fast.

    The “brute force search” may or may not be so-bad. If the hash is very large and virtual-storage is not, then the potential exists that walking through that hash is going to trigger a slew of page-faults every time, and that's really bad. But if storage is plentiful then it's all probably sitting in real-RAM anyway and you can just blip-through all that storage at CPU-speed. So basically it comes down to the practical likelihood of page-faults.

Re: getting hash key with value (List::Pairwise)
by lodin (Hermit) on Apr 17, 2008 at 10:08 UTC

    This is trivial using List::Pairwise, even if the values aren't unique.

    use List::Pairwise 'mapp'; my %hash = ( foo => 1, bar => 2, baz => 1, bux => 0, ); my $val = $hash{foo}; my @keys = mapp { $b eq $val ? $a : () } %hash; print "@keys"; __END__ baz foo
    Even if you think that your values are unique it's sometimes a good idea to assert this:
    my ($key, @too_many) = mapp { $b eq $val ? $a : () } %hash; ! @too_many or die 'Too many ...';


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://680691]
Approved by ww
[makita]: Need to sign more elements but all types I put in array are ignored. And is always signed only the body
[Discipulus]: no makita sorry. i see in the synopsis of the module: "WARNING: Only limited real-life experience" might be better compose a SOPW with some code example and data
[Discipulus]: ..or inspect the source code of the module
[makita]: I am doing this:
[makita]: my $sig = $wss->signature( schema => $wsdl, token => $token, sign_types=>'wsa: Action','wsa:To', 'wsu:Timestamp', 'wsa:MessageID',' SOAP-ENV:Body', signer=>DSIG_RSA_S HA1, public_key => $cert,
[Corion]: Oof, I haven't done much with signing SOAP requests. markov is usually somebody good to ask via mail ;)
[makita]: I need to create a SOAP call where are signed more types not only the body
[makita]: I am inspecting it second day :)
[makita]: Thanks
[Discipulus]: better to ask a full SOPW

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (11)
As of 2017-03-23 08:45 GMT
Find Nodes?
    Voting Booth?
    Should Pluto Get Its Planethood Back?

    Results (285 votes). Check out past polls.