3

我有以下 Perl 代码。

#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;

my @array = (  3, 4, 1, 4, 7, 7, 4, 1, 3, 8 );
my %unordered;
@unordered{@array} = undef;

foreach my $key (keys %unordered) {
print "Unordered: $key\n";
}

my %seen;
my @ordered;

foreach my $element (@array) {
  if (  not $seen{$element}++ ) {
    push @ordered, $element;
  }
}

在最后一个foreach代码块中,我无法理解这一点 - 在第一次迭代中,表达式的not $seen{$element}++计算结果为非 0 - true - 所以 if 块执行。在第二次迭代中,表达式not $seen{$element}++应该再次评估为非 0 - true,因为哈希为空。因此,读取标量$seen{$element}将读取 0 而不是 0 将评估为真。因此,if 块应该再次执行。但是,这本书说它在第一次迭代后停止。谁能解释一下?

4

2 回答 2

2

在第二次迭代中,哈希将不再为空,因为++操作员将 a1放入其中。在第三次迭代中,该值将是2(就本程序而言,它与 相同1,仅表示“之前至少见过一次”)。

在您的程序结束时%seen将包含每个条目在您的列表中出现的次数。

if $a++递增 的值$a(如果缺失,则将其视为 0),然后将该递增之前的值返回给比较。

使用后缀运算符很重要,因为if ++$a在这里不起作用:它还会1在您的哈希中放置 a,但它会返回修改后的值(1即使是第一次迭代也是如此)。

于 2013-09-08T05:20:04.400 回答
0

最后一个 foreach 循环可以详细说明为:

# loop on all elements of the array
foreach my $element (@array) {
    # if the current element haven't been seen yet
    if ( not exists $seen{$element} ) {
        # add current element into ordered array
        push @ordered, $element;
    }
    # Increment the number of time element have been seen
    $seen{$element}++;
}

最后,@ordered将包含:

(3, 4, 1, 7, 8)

一个更好的名字应该是@unique代替@ordered.

%seen将包含:

(3 => 2, 4 => 3, 1 => 2, 7 => 2, 8 => 1)
于 2013-09-08T09:00:28.373 回答