Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Print keys corresponding to duplicate values

by amar712 (Initiate)
on Apr 27, 2016 at 22:01 UTC ( [id://1161703]=perlquestion: print w/replies, xml ) Need Help??

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

I have a hash %hash = { 'a' => 1, 'b' => 2, 'c' => '1', 'd' => 3, 'e' => '5' } How can I return the keys with the same value. In the above example I want a,c.
  • Comment on Print keys corresponding to duplicate values

Replies are listed 'Best First'.
Re: Print keys corresponding to duplicate values
by NetWallah (Canon) on Apr 27, 2016 at 23:24 UTC
    use strict; use warnings; use feature 'say'; my %hash = ( 'a' => 1, 'b' => 2, 'c' => '1', 'd' => 3, 'e' => '5'); my (%seen,@dups); while (my($k,$v)=each %hash){ if ( defined $seen{$v}){ push @dups,$k; $seen{$v} and push @dups,$seen{$v}; $seen{$v}=''; next } $seen{$v}=$k } say for sort @dups; __OUTPUT__ a c

            This is not an optical illusion, it just looks like one.

Re: Print keys corresponding to duplicate values
by davido (Cardinal) on Apr 27, 2016 at 23:44 UTC

    This solution inverts the hash like this:

    k1 v1 k2 v2 k3 v1 v1 v2 (a => 1, b => 2, c => 1) => (1 => [a,c], 2 => [b])

    Then it just becomes a matter of finding those value-keys who point to more than a single original key name.

    use strict; use warnings; my %hash = (a => 1, b => 2, c => 1, d => 3, e => 5); my @non_unique = duplicated_values_keys(%hash); print "$_\n" for @non_unique; sub duplicated_values_keys { my %hash = @_; my %inverted; push @{$inverted{$hash{$_}}}, $_ for keys %hash; return map {@{$inverted{$_}} > 1 ? @{$inverted{$_}} : ()} keys %in +verted; }

    Outputs:

    a c

    ...in no particular order.


    Dave

Re: Print keys corresponding to duplicate values
by FreeBeerReekingMonk (Deacon) on Apr 27, 2016 at 22:19 UTC
    You need to loop through your keys, and check if your values are the same. Usually one uses another hash %SEEN to store the reverse: value-to-key (instead of key-to-value) while looping over the keys...

    ANOTHER idea is to loop over the values:

    for my $val (values %hash){

    And detect FIRST which ones you already seen (using %SEEN in a numerical fashion), before looping through the keys and knowing the value, look it up if you seen it already.

    Also, write your hash definition like this:

    use strict; use warnings; my %hash = ( 'a' => 1, 'b' => 2, 'c' => '1', 'd' => 3, 'e' => '5' );

    keys

Re: Print keys corresponding to duplicate values
by tangent (Parson) on Apr 27, 2016 at 23:29 UTC
    As FreeBeerReekingMonk suggests, the %seen style of hash is often used for counting duplicates:
    my %seen; $seen{$_}++ for values %hash; my @dups = grep { $seen{ $hash{$_} } > 1 } keys %hash; print join(',', sort @dups );
Re: Print keys corresponding to duplicate values
by Anonymous Monk on Apr 27, 2016 at 22:15 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1161703]
Approved by Paladin
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (6)
As of 2024-04-23 23:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found