看起来非常简单,我想出了大部分内容。但是看到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 );
}
所以我在这一点上的理解是:
++
做了什么),请跳到下一次迭代我遗漏了两件事:
我知道问题出在这一部分:
$seen{ $elem }++
我怀疑它是在做一堆不同的东西。是否有更简单更简洁的方式来写这条线?
感谢您的帮助
答案 0 :(得分:4)
++
运算符在Perl中的功能基本上与在大多数其他语言中运行相同:它会增加变量。
$seen{ $elem }++;
增加%seen
中的值,即密钥为$elem
的值。
“神奇”是如果尚未定义$seen{$elem}
,则会自动创建它,就像它已经存在并且值为0一样; ++
然后将其设置为1.所以它相当于:
if (! exists $seen{$elem}) {
$seen{$elem} = 0;
}
$seen{$elem} ++;
这称为“autovivification”。 (不,真的,这就是所谓的。)(编辑2:不,我的错误,不是;正如@ysth所指出的那样,“自动化”实际上是指引用即将存在。请参阅{{1 }}。)
编辑:以下是您的描述的修订版本:
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放入独特元素的列表(数组)中。