2

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?

3 Answers 3

8

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. That explains it very well.
1

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
        };

Comments

0

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
);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.