2

我在使用从数组派生的哈希时遇到了一些麻烦。对于我知道存在的元素,它未能通过“存在”测试。我写了小测试代码来确认这一点。这里是:

#!/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";
    }
}

这是示例输出:

2 exists!
3 DOES NOT exist.
5 exists!
7 DOES NOT exist.
11 exists!
13 DOES NOT exist.
17 exists!
19 DOES NOT exist.

我究竟做错了什么?

4

3 回答 3

8

分配给哈希时,需要交替键和值的列表。以下将解决您的问题:

my %sieve_hash = map { $_ => 1 } @sieve;

有了上述内容,一个简单的真值测试(而不是存在测试)就足够了。但是由于您使用的是存在测试,因此您可以通过使用以下分配undef而不是来节省一些内存1

my %sieve_hash;
@sieve_hash{ @sieve } = ();

或者

my %sieve_hash;
$sieve_hash{$_} = undef for @sieve;

不过,我发现真值测试要优雅得多。

于 2013-05-16T04:42:42.000 回答
1

当您将数组分配给哈希时,偶数索引元素,例如 $sieve[0]、$sieve[2] 成为哈希键,奇数元素 $sieve[1]、$sieve[3] 等成为哈希值。您会注意到输出中的模式,其中只有每个其他元素(第 0 个、第 2 个、第 4 个)“存在”作为哈希中的键。

使用 Data::Dumper 查看发生了什么:

#!/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
        };
于 2013-05-16T05:24:08.847 回答
0

当你说

my %sieve_hash = @sieve;

它将数组的每个其他元素作为键,其他元素作为值。

所以你的哈希看起来就像它是由以下构造的一样:

my %sieve_hash = (
  2 => 3,
  5 => 7,
  ... and so on
);
于 2013-05-16T04:43:28.823 回答