Re: Common hash keys by parv (Priest) on Jun 07, 2008 at 07:30 UTC |
for all keys in hash-1, where k-1 is current key
for all keys in hash-2, where k-2 is current key
put k-1 in store if k-1 = k-2
end-for
end-for
# "store" would have all the common keys in the end
Time passes. Oh yes, finding if any keys are present ...
common set to false
for all keys in hash-1, where k-1 is current key
for all keys in hash-2, where k-2 is current key
if k-1 = k-2,
common set to true
break out of both loops
end-for
end-for
# test common to check for commonality
| [reply] [d/l] [select] |
|
Your inner loop could be described as clubbing somebody to death with a loaded uzi. No need to iterate over the hash keys just to check if one is present. Looking up a key in a hash is the most basic operation a hash offers ;-)
| [reply] |
|
| [reply] |
|
|
|
Re: Common hash keys by moritz (Cardinal) on Jun 07, 2008 at 07:36 UTC |
This is described (in a slight variation) in perlfaq4. If you have problems with having references and not the hash itself, read perlreftut. | [reply] |
|
Data: Hashes (Associative Arrays)
How do I process an entire hash?
What happens if I add or remove keys from a hash while iterating ove
+r it?
How do I look up a hash element by value?
How can I know how many entries are in a hash?
How do I sort a hash (optionally by value instead of key)?
How can I always keep my hash sorted?
What's the difference between "delete" and "undef" with hashes?
Why don't my tied hashes make the defined/exists distinction?
How do I reset an each() operation part-way through?
How can I get the unique keys from two hashes?
How can I store a multidimensional array in a DBM file?
How can I make my hash remember the order I put elements i into it?
Why does passing a subroutine an undefined element in a hash create
+it?
How can I make the Perl equivalent of a C structure/C++ class/hash
+or array of hashes or arrays?
How can I use a reference as a hash key?
relate to my question. Which for clarity I will restate. How can I determine if there are any common keys in two hashes to which I have references.
Specifically, the code
if(@{$refa}{keys %{$refb}}) {
#
}
does not work.
If you do not know the answer, perhaps you could let someone who does respond? Instead of linking to a generic section of Q&As that you think (hope) might answer it.
If you really believe one of those does answer the question, then perhaps you could link directly to it, rather than just waving your hands in a general direction: "it's over there somewhere". | [reply] [d/l] [select] |
|
Sorry, but none of these (...) relate to my question.
Well, they are not the only topics in perlfaq4. I was referring to intersection of arrays. keys %hash is a list after all, and although the FAQ speaks of arrays, it works for lists as well.
| [reply] [d/l] |
|
|
|
|
Anonymous--
Sorry, but none of these
Data: Hashes (Associative Arrays)
<<<snip>>>
How can I get the unique keys from two hashes?
<<<snip>>>
relate to my question.
You suffer from a failure of the imagination. The preceding item does relate to your question. It's the complementary action to the one you requested. Compute the list of unique keys and all your keys not on that list are the ones common to your two hashes. Alternatively, modify the algorithm to keep the keys that don't satisfy the uniqueness criterion and you have the list of keys you want.
If that's not obvious, you might want to reconsider your career choices...or at least refrain from posting snotty replies to any assistance you are given.
...roboticus
| [reply] [d/l] |
|
|
Re: Common hash keys by casiano (Pilgrim) on Jun 07, 2008 at 10:01 UTC |
If you want to know which keys they have in common:
DB<1> %a = (a => 1, b =>2, c => 3); %b = (b =>2, c => 1, d => 4)
DB<2> $seen{$_}++ for (keys(%a), keys(%b))
DB<3> x grep { $seen{$_} > 1 } keys(%seen)
0 'c'
1 'b'
If the only thing you want is to know if they have some key in common:
DB<1> use List::Util qw{first}
DB<2> %a = (a => 1, b =>2, c => 3); %b = (b =>2, c => 1, d => 4)
DB<3> x first { ++$seen{$_} > 1 } (keys(%a), keys(%b))
0 'c'
Hope it helps
| [reply] [d/l] [select] |
|
DB<2> $seen{$_}++ for (keys(%a), keys(%b))
DB<3> x grep { $seen{$_} > 1 } keys(%seen)
You can combine these two into a single statement:
use Data::Dump;
my %a = ( a => 1, b => 2, c => 3 );
my %b = ( b => 2, c => 1, d => 4 );
my %seen;
pp grep { $seen{$_}++ } keys %a, keys %b;
Update: Don't use state variables for this. See lodin's reply
Or, with 5.10
pp grep { state %seen; $seen{$_}++ } keys %a, keys %b;
| [reply] [d/l] [select] |
|
use 5.010;
sub foo {
my ($a, $b) = @_;
sort grep { state %seen; $seen{$_}++ } keys %$a, keys %$b
}
my %a = ( a => 1, b => 2, c => 3 );
my %b = ( b => 2, c => 1, d => 4 );
say join ' ', foo(\%a, \%b);
say join ' ', foo(\%a, \%b);
__END__
b c
a b b c c d
Here you should just stick with my.
lodin | [reply] [d/l] [select] |
Re: Common hash keys by apl (Monsignor) on Jun 07, 2008 at 12:33 UTC |
Ignoring CPAN modules, If you can't think of at least two purely mechanical ways of solving this problem, you need to either read (among other things) Data Type: Hash, or drop the class you're in. | [reply] |
Re: Common hash keys by throop (Chaplain) on Jun 07, 2008 at 13:23 UTC |
use strict;
use vars qw($hashRef1 $hashRef2);
#code that puts values into the hashes
my @keyIntersection =
grep exists($hashRef2->{$_}), keys %$hashRef1;
# Or if you just want to know if there are any
use List::Util;
my $hasInt =
first {exists $hashRef2->{$_}} keys %$hashRef1;
$hasInt will be undef unless there's an intersection.
But be careful, it will be 0 if the first interecting key is '0'
throop | [reply] [d/l] |
|
use List::Util 'first';
if(first{exists $hashRef2->{$_}} keys %$hashRef1 )
#
}
| [reply] [d/l] |
|
use List::Util;
my $hasInt =
defined
first { exists $hashRef2->{$_} }
keys %$hashRef1
;
lodin | [reply] [d/l] |
|
Actually, there's no need to be careful or test for definedness.
List::Util::first() returns the result of the code block, in this case the boolean return of the exists function. The values associated with the keys never come into it.
use List::Util qw[ first ];;
my $a = { a=>0, b=>0, c=>0 };
my $b = { c=>0, d=>0, e=>0 };
if( first{ exists $b->{ $_ } } keys %$a ) {
print "Common keys!";
}
Common keys!
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |
|
|
Re: Common hash keys by ferreira (Chaplain) on Jun 07, 2008 at 14:45 UTC |
my @common_keys = grep { exists $hash1->{$_} } keys %$hash2;
| [reply] [d/l] |
Re: Common hash keys by injunjoel (Priest) on Jun 08, 2008 at 20:46 UTC |
For the sake of esoteric aesthetics...
#!/usr/bin/perl -w
use strict;
my %a = ('a' =>1, 'b'=>2, 'c'=>5, 'd'=>19);
my %b = ('b'=>12, 'd'=>32, 'z'=>77, 'y'=>5);
my @common_keys =
do{
local %_;
$_{$_}++ for(keys %a, keys %b);
delete @_{(map{ ($_{$_} == 1) ? $_ : ()}keys %_)};
sort keys %_;
};
print "@common_keys";
-InjunJoel
"I do not feel obliged to believe that the same God who endowed us with sense, reason and intellect has intended us to forego their use." -Galileo
| [reply] [d/l] |
Re: Common hash keys by wade (Pilgrim) on Jun 09, 2008 at 16:06 UTC |
Is it possible, given that the OP was so terse and so aggressive (in later posts, though I admit that I'm making assumptions), that this is a troll?
| [reply] |
|
And look at who was aggressively defending the aggressive troll...
| [reply] |
|
| [reply] |
Re: Common hash keys by radiantmatrix (Parson) on Jun 09, 2008 at 20:46 UTC |
OK, let's walk through this.
A hash reference is just a reference to a hash, getting at the hash is a simple matter -- so we can ignore the "reference" part of your question for now, and focus on how to determine if two hashes share any keys. Let's start with two simple hashes:
%a = ( one=>1, two=>2, three=> 3 );
%b = ( two=>'two', three=>'three', four=>'four');
We know the keys they have in common are two and three, but how to find that out in code?
First, let's rephrase the question a little bit: if I know all the keys in one hash, how do I find out if any of those keys exist in another hash?
Let's work backwards from that. How do we find out if the %a hash contains a key -- let's say, the key one? That would be exists:
if (exists $a{one}) { print "\%a has 'one' for a key" }
Ok, so how do we find out what keys a hash has? How about keys:
print join(",", keys %a); # prints "one,two,three"
So, if we get the list of keys for hash %a, all we have to do is loop through them and see if %b has any that match. Here's the long way:
my @common_keys;
foreach my $key (keys %a) {
if (exists $b{$key}) {
print "\%a and \%b have key '$key' in common\n";
push @common_keys, $key;
}
}
Make sense? Of course, this type of activity -- looking through a list to find items that meet a criterion -- is so common that Perl has a function for it: grep. So here's a short version:
my @common_keys = grep { exists $b{$_} } keys(%a);
Now let's add "references" back to the mix. Let's make references to our hashes:
$x = \%a;
$y = \%b;
Now, we do as above, but dereferencing as appropriate:
my @common_keys = grep { exists $y->{$_} } keys( %{ $x } );
We pass the whole hash referenced by $x to keys; and we use the dereference operator -> to make sure that exists looks at the hash referenced by $y.
<–radiant.matrix–>
Ramblings and references
“A positive attitude may not solve all your problems, but it will annoy enough people to make it worth the effort.” — Herm Albright
I haven't found a problem yet that can't be solved by a well-placed trebuchet
| [reply] [d/l] [select] |