试图理解这个perl脚本

时间:2011-08-08 15:19:06

标签: perl analysis

看起来非常简单,我想出了大部分内容。但是看到perl的语法松散,新来者很难直接进入:)

my @unique = ();
my %seen   = ();
foreach my $elem ( @array ) {
    next if $seen{ $elem }++;
    push @unique, $elem;
}

这是来自perldoc网站的。如果我理解正确,它也可以写成:

my @unique = ();
my %seen   = ();
my $elem;
foreach $elem ( @array ) {
    if ( $seen{ $elem }++ ) {
        next;
    }
    push ( @unique, $elem );
}

所以我在这一点上的理解是:

  • 声明一个名为unique
  • 的数组
  • 声明名为
  • 的哈希
  • 声明名为elem
  • 的变量
  • 迭代@array,每次迭代都存储在$ elem
  • 如果$ elem是看到的哈希值中的一个键(我不知道++做了什么),请跳到下一次迭代
  • 将$ elem附加到@unique
  • 的末尾

我遗漏了两件事:

  • 什么时候存储在%中?
  • ++做什么(用其他语言增加,但我看不出它是如何工作的)

我知道问题出在这一部分:

$seen{ $elem }++

我怀疑它是在做一堆不同的东西。是否有更简单更简洁的方式来写这条线?

感谢您的帮助

4 个答案:

答案 0 :(得分:4)

++运算符在Perl中的功能基本上与在大多数其他语言中运行相同:它会增加变量。

$seen{ $elem }++;

增加%seen中的值,即密钥为$elem的值。

“神奇”是如果尚未定义$seen{$elem},则会自动创建它,就像它已经存在并且值为0一样; ++然后将其设置为1.所以它相当于:

if (! exists $seen{$elem}) {
    $seen{$elem} = 0;
}
$seen{$elem} ++;

这称为“autovivification”。 (不,真的,这就是所谓的。)(编辑2:不,我的错误,不是;正如@ysth所指出的那样,“自动化”实际上是指引用即将存在。请参阅{{1 }}。)

编辑:以下是您的描述的修订版本:

  • 声明名为@unique
  • 数组变量
  • 声明名为%seen
  • 哈希变量
  • 声明名为$ elem
  • 标量变量
  • 迭代@array,每次迭代都存储在$ elem
  • 如果$ elem是所见哈希值的关键字,请跳至下一次迭代
  • $ elem的值附加到@unique
  • 的末尾

perldoc perlref@unique%seen都是变量。标点字符(称为“sigil”表示它们各自的变量类型,最好被认为是名称的一部分。

答案 1 :(得分:3)

  

什么时候存储在%see中?

当它试图增加它时。

  

++做什么(用其他语言增加,但我看不出它是如何工作的)

增加未定义的变量使其成为1

它与此相同:

my @unique = ();
my %seen   = ();
my $elem;
foreach $elem ( @array ) {
    if ( ! $seen{ $elem } ) {
         $seen{ $elem } = 1;  
    } else {
        $seen{ $elem }++;
        push ( @unique, $elem );
    }
}

答案 2 :(得分:3)

这是Perl中用于创建由给定数组中的“唯一”元素组成的数组的常见模式。

在Perl中,哈希存储与任何给定键相关联的值。但是,如果您没有在给定键的哈希中放置任何内容,则会得到undef - 但在数字上下文中,例如当您执行增量操作时,undef会被处理比如0,然后递增。

如您所知,if语句会检查true或false值。在Perl中,0"0"''(空字符串)和undef(可能还有其他?)被视为错误值。

与C / C ++ / Java类似,后增量将原始值返回到包含表达式。所以这段代码

if ( $seen{ $elem }++ ) {
        next;
    }
对于尚未看到的元素,

将返回false(0),并且循环将继续(即,不会运行next语句)。该元素将放入数组中。然而,在此之前,增量发生 - 现在突然1存储在哈希中,这意味着值已被看到一次。下次看到该值时,将跳过循环,并且该值不会再次添加到结果数组中。

答案 3 :(得分:1)

如果使用键$ elem看不到%中的元素,则此行将使用键$ elem创建一个新元素(哈希表中的新条目)。它后面的++是一个增量运算符。它为$ seen {$ elem}的值增加了一个。由于$ seen {$ elem}的初始值计算为false,或者在数值上下文中为零,因此将$ see {elem}的值增加1。由于++位于$ seen {$ elem}的右侧,因此仅在$ seen {elem}被评估后才添加。因此,第一次遇到任何特定的$ elem时,此测试将失败,它将进入下一步,将$ elem放入独特元素的列表(数组)中。