Watcom C/C++
  Contact Us

Inverting a hash

Back to Perl Examples
You can think of this as an expansion on How do I look up a hash element by value? in perlfaq4.

Typically, if you want to invert a hash, you use reverse:

    %inverted = reverse %original;

Unfortunately this won't work if you have have duplicate values in the hash.

Here's a way to invert a hash, that preserves duplicate values:

    sub invert_hash (\%) {
        my ($orig) = @_;
        my $result = {};
        while (my ($key, $value) = each %$orig) {
            push @{$result->{$value}}, $key;
        return $result;
This will return a hash which has references to anonymous arrays in each element.

To use this:

    use Data::Dumper;
    %x = ( a=>1, b=>2, c=>1, d=>1, e=>2, f=>3 );
    print Dumper(\%x);
    %y = reverse %x; # the FAQ method, which shouldn't be used here
    %z = %{invert_hash(%x)};
    print "reverse: keys which have value 1: ",join(',', $y{1}),"\n";
    print "invert_hash: keys which have value 1: ", join(',', @{$z{1}}), "\n";
This should produce a result like:

    $VAR1 = {
              'a' => 1,
              'b' => 2,
              'c' => 1,
              'd' => 1,
              'e' => 2,
              'f' => 3
    reverse: keys which have value 1: a
    invert_hash: keys which have value 1: a,c,d
Note that the inverted hash produced with invert_hash() has all the keys which had the value 1.