For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > October 2006 > unique hash keys









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author unique hash keys
Romeo Theriault

2006-10-23, 7:57 am

Hi, I'm playing with hashes trying to get myself more familiar with
them. I have a little program below that has a hash with some keys
and values in it. The program then copies some of the values/keys to
another hash depending on their values. This all works fine, but in
the last step of the program I am trying to get the program to tell
me key's that are unique to only the first hash. No matter what I do
it always prints out all of the values in the first hash, not the
keys that are unique to only the first hash.

Thank you for any help.

Romeo


#!/usr/bin/perl

use strict;
use warnings;

my %hash;
my %dbmhash;
my $key_h;
my $key_dbm;
my %onlyinfirsthash;
my $key_f;


dbmopen(%dbmhash, "dbmfilename", 0644)
or die "cannot open DBM";

%hash = (
picard => '789',
lego => '788',
joe3 => '787',
simone => '788',
joe => '800',
catdog => '9000',
moneydog => '8090',
);


foreach $key_h (keys %hash) {
print "$key_h from standard hash has a value of $hash{$key_h}\n";
if ($hash{$key_h} <= 788) {
$dbmhash{"$key_h"} = $hash{$key_h};
#print "$key has a value of $hash{$key}\n";
}
}

print "\n\n";

foreach $key_dbm (keys %dbmhash) {
print "$key_dbm from dbmhash has a value of $dbmhash{$key_dbm}\n";
}

print "\n\n";

foreach $key_h (keys %hash) {
foreach $key_dbm (keys %dbmhash) {
unless ($key_h eq $key_dbm) {
print "$key_h\n";
}

}
}

Paul Lalli

2006-10-23, 7:57 am

Romeo Theriault wrote:
> Hi, I'm playing with hashes trying to get myself more familiar with
> them. I have a little program below that has a hash with some keys
> and values in it. The program then copies some of the values/keys to
> another hash depending on their values. This all works fine, but in
> the last step of the program I am trying to get the program to tell
> me key's that are unique to only the first hash. No matter what I do
> it always prints out all of the values in the first hash, not the
> keys that are unique to only the first hash.


You need to get your terminology right. You are looping over the keys,
and printing out the keys. You are not printing out the values at all.
"key" and "value" are very specific and very important terms when
you're talking about hashes.

> foreach $key_h (keys %hash) {
> foreach $key_dbm (keys %dbmhash) {
> unless ($key_h eq $key_dbm) {
> print "$key_h\n";
> }
>
> }
> }


Your problem is one of logic, not syntax. You have two sets of things
your looping over. Let's say that's:
alpha one beta
one two three

You loop over the first set, and compare each item to each item in the
second set. If those two are not equal, you print out the one from the
first set. So the comparisons you're going to make are:
alpha - one (not equal, print alpha)
alpha - two (not equal, print alpha)
alpha - three (not equal, print alpha)
one - one (equal, don't print)
one - two (not equal, print one)
one - three (not equal, print one)
beta - one (not equal, print beta)
beta - two (not equal, print beta)
beta - three (not equal, print beta)

As you can see, you're going to print all the items from the first set
no matter what. It's just that if the second set contains an item from
the first, that item will be printed one less time.

Your code should not be making use of two loops. It should be one loop
and one check for existance:

foreach $key_h (keys %hash) {
if ( ! exists($dbmhash{$key_h}) ) {
print "$key_h\n";
}
}


Paul Lalli

Adriano Ferreira

2006-10-23, 7:57 am

On 10/23/06, Romeo Theriault <romeotheriault@gmail.com> wrote:
> This all works fine, but in
> the last step of the program I am trying to get the program to tell
> me key's that are unique to only the first hash. No matter what I do
> it always prints out all of the values in the first hash, not the
> keys that are unique to only the first hash.


> foreach $key_h (keys %hash) {
> foreach $key_dbm (keys %dbmhash) {
> unless ($key_h eq $key_dbm) {
> print "$key_h\n";
> }
>
> }
> }


Romeo,

You are not doing what you said. The loop above prints the keys of the
first hash which differs from every key of the second hash. That
explains why it seemingly prints out all of the values.

foreach $key_h (keys %hash) {
print "$key_h\n" unless exists $dbmhash{$key_h};
}

will work better.
Romeo Theriault

2006-10-23, 6:57 pm

On Oct 23, 2006, at 8:45 AM, Adriano Ferreira wrote:

> On 10/23/06, Romeo Theriault <romeotheriault@gmail.com> wrote:
>
>
> Romeo,
>
> You are not doing what you said. The loop above prints the keys of the
> first hash which differs from every key of the second hash. That
> explains why it seemingly prints out all of the values.
>
> foreach $key_h (keys %hash) {
> print "$key_h\n" unless exists $dbmhash{$key_h};
> }
>
> will work better.



Thank you Adriano, that works nicely after I added:

use Memoize::AnyDBM_File;

before that I was getting this error:

AnyDBM_File doesn't define an EXISTS method at ....

I did a bit of googling and found that solution.

But I do have a question about your solution.
> foreach $key_h (keys %hash) {
> print "$key_h\n" unless exists $dbmhash{$key_h};
> }


I don't understand why $dbmhash{$key_h} refers to the key whereas
earlier in the code when I do:

if ($hash{$key_h} <= 788) {
$dbmhash{"$key_h"} = $hash{$key_h};
}

$hash{$key_h} <= 788 is looking at the key value?



Thanks,

Romeo
Paul Lalli

2006-10-23, 6:57 pm

Romeo Theriault wrote:
> But I do have a question about your solution.
>
> I don't understand why $dbmhash{$key_h} refers to the key whereas
> earlier in the code when I do:
>
> if ($hash{$key_h} <= 788) {
> $dbmhash{"$key_h"} = $hash{$key_h};
> }
>
> $hash{$key_h} <= 788 is looking at the key value?


Once again, your terminology is skewed. "key value" is nonsensical.
There are keys, and there are values. In *general*, $hash{$key_h}
means "the value of the hash %hash which associated with the key
$key_h". However, as the argument to the exists() function, this
notation lets us ask "does this key/value pair exist in this hash?" We
don't care what the value is, we simply want to know if that value (and
therefore that key) exists.

Paul Lalli

Adriano Ferreira

2006-10-23, 6:57 pm

On 10/23/06, Romeo Theriault <romeotheriault@gmail.com> wrote:
> Thank you Adriano, that works nicely after I added:
>
> use Memoize::AnyDBM_File;
>
> before that I was getting this error:
>
> AnyDBM_File doesn't define an EXISTS method at ....


I had not payed much attention to the fact that your code were using
ties rather than simple hashes. I did not know either AnyDBM_File ties
missed EXISTS method (if it had an EXISTS, it should have been
transparent to you). But there must be some good reason, like not
caching by default to avoid performance penalties.

> But I do have a question about your solution.
>
> I don't understand why $dbmhash{$key_h} refers to the key whereas
> earlier in the code when I do:
>
> if ($hash{$key_h} <= 788) {
> $dbmhash{"$key_h"} = $hash{$key_h};
> }
>
> $hash{$key_h} <= 788 is looking at the key value?


* A simple thing like $hash{foo} looks at the value of %hash stored at
"foo" value.
* $hash{'foo'} does the same.
* $hash{"foo"} does the same.
* $hash{$foo} uses what's stored at $foo as the key.
* $hash{"$foo"} uses the result of "$foo" (an interpolation) as the key

But if $key_h is a string, "$key_h" is just the same as $key_h.
Romeo Theriault

2006-10-23, 6:57 pm

On 10/23/06, Adriano Ferreira <a.r.ferreira@gmail.com> wrote:
> On 10/23/06, Romeo Theriault <romeotheriault@gmail.com> wrote:
>
> I had not payed much attention to the fact that your code were using
> ties rather than simple hashes. I did not know either AnyDBM_File ties
> missed EXISTS method (if it had an EXISTS, it should have been
> transparent to you). But there must be some good reason, like not
> caching by default to avoid performance penalties.
>
>
> * A simple thing like $hash{foo} looks at the value of %hash stored at
> "foo" value.
> * $hash{'foo'} does the same.
> * $hash{"foo"} does the same.
> * $hash{$foo} uses what's stored at $foo as the key.
> * $hash{"$foo"} uses the result of "$foo" (an interpolation) as the key
>
> But if $key_h is a string, "$key_h" is just the same as $key_h.
>

Ok, thank you, I hadn't noticed the distinctions before.
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com