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

hi monks,
I have 5 hashes,inthese some key values are repeating in all the hashes,how can i list those keys which are occuring in more than one hash.
  • Comment on how can i return the common keys from a hash

Replies are listed 'Best First'.
Re: how can i return the common keys from a hash
by BrowserUk (Patriarch) on Aug 04, 2006 at 21:52 UTC

    Use another hash to count the keys: (Corrected: Pre- not post-increment)

    %h= 1..10; %i = 1.. 20; %j = 3..8; %k = 9 .. 18;; %l = 1 .. 14;; %x = ();; print grep{ ++$x{ $_ } == 2 } sort{ $a <=> $b } map{ keys %$_ } \( %h, %i, %j, %k, %l,);; 1 3 5 7 9 11 13 15 17

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: how can i return the common keys from a hash
by imp (Priest) on Aug 04, 2006 at 21:54 UTC
    Here are a two possible ways to find which keys appear in multiple hashes. Neither of these will report how many occurrences, or which hash they appear in - but either would be fairly easy to add.
    use strict; use warnings; my %hash1 = (a => 1, b => 2); my %hash2 = (a => 1, c => 3); my %hash3 = (d => 1, c => 3); # Method 1 # Create a hash for tallying the number of times keys occur in the oth +er hashes. my %key_bucket = (); for my $key (keys %hash1, keys %hash2, keys %hash3) { $key_bucket{$key}++; } my @duplicates = grep {$key_bucket{$_} > 1} keys %key_bucket; print "Method 1:\n"; print "$_\n" for @duplicates; # Method 2 # Create a list of unique keys, then check how many hashes each key ap +pears in print "Method 2:\n"; my %unique = map {$_ => 1} keys %hash1, keys %hash2, keys %hash3; for my $key (keys %unique) { my (@matches) = grep {exists $_->{$key}} \%hash1, \%hash2, \%hash3 +; print "$key\n" if @matches > 1; }
Re: how can i return the common keys from a hash
by GrandFather (Saint) on Aug 04, 2006 at 22:52 UTC

    Build a list of references to the hashes. Use map to build a key count. Use grep to find duplicate keys:

    use strict; use warnings; # The hashes my %hash1 = (1..6); my %hash2 = (1..4, 7..10); my %hash3 = (1, 2, 9..12); # Build the list of hash references my @hashList = (\%hash1, \%hash2, \%hash3); my %keyCount; # Count the keys map {$keyCount{$_}++} keys %$_ for @hashList; # Find duplicates my @common = sort grep {$keyCount{$_} == @hashList} keys %keyCount; print "@common";

    Prints:

    1

    DWIM is Perl's answer to Gödel
Re: how can i return the common keys from a hash
by Hue-Bond (Priest) on Aug 04, 2006 at 21:52 UTC

    This is a typical intersection problem. Yes, a FAQ. Go read perlfaq4. You basically create some arrays with the hash keys and perform the intersection over them.

    Update: Hmm, seems I misread "values". Well, you can perform the intersection of the values as it's explained in the FAQ. For obtaining the corresponding keys, you can reverse the hash:

    my %c = ( a=>1, b=>2, c=>3 ); my %rev_c = reverse %c; use Data::Dumper;print Dumper \%rev_c; __END__ $VAR1 = { '1' => 'a', '3' => 'c', '2' => 'b' };

    Of course, you're going to have problems if there's more than one key with the same value, since the action of reversing the hash will eliminate all of those keys but one.

    --
    David Serrano

Re: how can i return the common keys from a hash
by perladdict (Chaplain) on Aug 04, 2006 at 22:02 UTC
    If u want to return the common keys from hashes,use the fallowing sub to pass hash ref as arguments to sub.
    @repeat=common(\%a,\%b,\%c); sub common { my %d; for my $href(@_) { while(my $m=each %$href) $d{$m}++; } } return grep {$d{$_} ==@_} keys %d }
      I am somewhat puzzled by the following DWIM:

      in scalar context, each returns the next key of the hash. Why doesn't, then, the assignment "my $m = each %$href" return false if the key is "0"? ie

      > perl -wle 'my %a = ( 0 => 1, y => 2, z => 4); while (my $m = each %a +) { print $m }' y 0 z > perl -wle 'my @a = ( 0 => 1, y => 2, z => 4); while (my $m = pop @a) + { print $m }' 4 z 2 y 1 > perl -wle 'my @a = ( 0 => 1, y => 2, z => 4); while (my $m = shift @ +a) { print $m }' >
        perl -MO=Deparse -wle 'my %a = ( 0 => 1, y => 2, z => 4); while (my $m + = each %a) { print $m }' BEGIN { $^W = 1; } BEGIN { $/ = "\n"; $\ = "\n"; } my(%a) = (0, 1, 'y', 2, 'z', 4); while (defined(my $m = each %a)) { print $m; }
        It checks for defined as the loop condition, not a true value.