I am having some trouble with using hash derived from array. It fails "exists" test for elements I know that are there. I wrote small test code to confirm this. Here it is:
#!/usr/local/bin/perl
my @sieve = (2, 3, 5, 7, 11, 13, 17, 19);
my %sieve_hash = @sieve;
foreach $prime (@sieve) {
if (exists($sieve_hash{$prime})) {
print "$prime exists!\n";
} else {
print "$prime DOES NOT exist.\n";
}
}
Here is sample output:
2 exists!
3 DOES NOT exist.
5 exists!
7 DOES NOT exist.
11 exists!
13 DOES NOT exist.
17 exists!
19 DOES NOT exist.
What am I doing wrong?
When assigning to a hash, a list of alternating keys and values are expected. The following would solve your problem:
my %sieve_hash = map { $_ => 1 } @sieve;
With the above, a simple truth test (rather than an existence test) would suffice. But since you're using an existence test, you could save some memory by using the following to assign undef instead of 1:
my %sieve_hash;
@sieve_hash{ @sieve } = ();
or
my %sieve_hash;
$sieve_hash{$_} = undef for @sieve;
I find a truth test much more elegant, though.
When you assign an array to a hash, the even indexed elements, e.g. $sieve[0], $sieve[2] become the hash keys, the odd numbered elements $sieve[1], $sieve[3], etc become the hash values. You'll notice the pattern in your output where only every other element (the 0th, 2nd, 4th) "exists" as a key in the hash.
Use Data::Dumper to see what's going on:
#!/usr/bin/perl
use Data::Dumper;
my @sieve = (2, 3, 5, 7, 11, 13, 17, 19);
my %sieve_hash = @sieve;
print STDERR "Your array:\n";
print Dumper \@sieve;
print STDERR "Your hash:\n";
print Dumper \%sieve_hash;
Your array:
$VAR1 = [
2,
3,
5,
7,
11,
13,
17,
19
];
Your hash:
$VAR1 = {
'11' => 13,
'17' => 19,
'2' => 3,
'5' => 7
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With