o2bwise has asked for the wisdom of the Perl Monks concerning the following question:

I can't believe I am asking for enhanced wisdom so soon after having asked for it before!

I just ran into what seems a conundrum, but I am sure it is simply an example of lack of coding expertise.

I am writing this code for work that includes a series of the following values. Two strings, each of which are unique and a numeric, which need not be unique. My desire is for the final output to be to list each string value and their corresponding numeric value in descending order of the numeric value.

I thought to use a hash where I concatenate the strings with some delimeter and use that as the key setting. And then let the value portion of the hash be the numeric.

And after the hash is fully populated, reverse sort the value setting into an array.

I have two questions.

1) What is the best way to "ask" for the setting of the key given a setting for the value? (I figured to just loop through the array with my output portion of the code.)

2) What of the case of more than one key,value pair having the same numeric value for the value? How does one code for extracting each key,value pair for output?

Tony
  • Comment on Hashes: Obtaining the Key Value for a Given Value Value

Replies are listed 'Best First'.
Re: Hashes: Obtaining the Key Value for a Given Value Value
by ikegami (Patriarch) on Feb 20, 2006 at 19:32 UTC
    • The following idiom works pretty well:

      my @keys = grep { $hash{$_} eq $value } keys %hash;

      Con: It doesn't scale nicely if you plan on doing a number of times.

    • If you want to iterate over the hash by value, you could create a hash whose keys are the values of the original hash and whose values are arrays of the keys of the original hash having those values. The following code creates this hash and displays it:

      my %reverse_hash; push{@{$reverse_hash{$hash{$_}}}, $_); foreach keys %hash; print(join(', ', @{$reverse_hash{$_)}), "\n"); foreach keys %reverse_hash;

      Con: Assumes the values are strings.

      Con: If you make any changes to %hash, you need to recompute %reverse_hash.

    • There's probably a module (using a tied hash) which provides an efficient solution by maintaining two hashes internally (one indexed by key, and one indexed by value).

      Update: Found Tie::Hash::TwoWay

      Thanks, ikegami.

      I'm all set!

      Tony
Re: Hashes: Obtaining the Key Value for a Given Value Value
by Roy Johnson (Monsignor) on Feb 20, 2006 at 19:35 UTC
    I think you just want to sort the keys based on the values:
    for my $k (sort { $hash{$a} <=> $hash{$b} } keys %hash) { print "$k: $hash{$k}\n"; }
    There's a module, Sort::Key, for doing it faster, though it likely won't matter.

    Caution: Contents may have been coded under pressure.
      Thanks, Roy.

      I used your snippet of code. That's sweet!

      I'm all set.

      Tony