Reputation: 197
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?
Upvotes: 2
Views: 109
Reputation: 386656
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.
Upvotes: 8
Reputation: 5757
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
};
Upvotes: 1
Reputation: 1921
When you say
my %sieve_hash = @sieve;
It takes one every other element of the array as a key, the other elements as the value.
So your hash look the same as if it was constructed from:
my %sieve_hash = (
2 => 3,
5 => 7,
... and so on
);
Upvotes: 0