http://qs321.pair.com?node_id=660759


in reply to How to get Keys from hash having same value?

Iterate through the keys of your hash, and look at the value of each one in turn.
for (keys %myhash) { print "$_ eq a\n" if $myhash{$_} eq 'a'; }

Replies are listed 'Best First'.
Re^2: How to get Keys from hash having same value?
by Thilosophy (Curate) on Jan 07, 2008 at 07:32 UTC
    Or, to avoid the extra hash lookups, iterate over key-value pairs using each.
    my @as = (); while (my ($key, $value) = each %myhash){ push @as, $key if $value eq 'a'; }

    Update:

    Is there a monk among us who can shorten this into a one-liner, similar to the grep keys examples we have seen?

    It seems that each does not combine nicely with grep, map and their ilk.

      Voilà:
      %newhash = reverse do { my $hash = reverse %myhash; %hash };

      To get the keys only (which are the values in the reversed hash:

      @unique_keys = do { my $hash = reverse %myhash; values %hash };

      update: oops, got it all wrong. It' about getting all keys where duplicate values are found. As a single statement, formatted for readability

      %myhash = (1 => 'a', 2=> 'b', 3=> 'a', 4=>'c',5 => 'b', 6 => 'a'); @k = do { my %s; map { my $v=$_; grep { $myhash{$_} eq $v} keys %myhash } grep {$s{$_}++==1} values %myhash }; print "$_ => $myhash{$_}\n" for @k; __END__ 6 => a 1 => a 3 => a 2 => b 5 => b

      Ah well. Readability... ;-)

      --shmem

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      I tried doing that, It is working.
      use Data::Dumper; %myhash = ( 1 => 'a', 2=> 'b', 3=> 'a', 4=>'c', 5 => 'a', 6 => 'a', 7 +=>'b'); %newhash = map { ($_,$myhash{$_}) } grep { $myhash{$_} eq 'a'; } keys + %myhash ; print Dumper \%newhash;