Re: how can i return the common keys from a hash
by BrowserUk (Patriarch) on Aug 04, 2006 at 21:52 UTC
|
%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.
| [reply] [d/l] |
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;
}
| [reply] [d/l] |
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
| [reply] [d/l] [select] |
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.
| [reply] [d/l] |
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
}
| [reply] [d/l] |
|
|
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 }'
>
| [reply] [d/l] [select] |
|
|
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. | [reply] [d/l] |
|
|