关于 Perl 地图函数的建议
Advice on Perl map function
我很难理解下面 Perl 脚本中 map 函数的行为
my @list = qw/A C T G/;
my @curr = (0, undef, undef, 1);
my @res = map { $list[ $_ ] } @curr;
print @res; #prints AAAC
@res
的值为AAAC
。我原以为它只是 AC
因为 @curr
的 2 个中间值是 undef
.
我对map的理解是list中的每一项依次成为$_
的值。所以我可以理解 $list[0]
returns A 和 $list[1]
returns C。我无法理解 why/how undef
值返回了 A ?在我看来 $list[undef]
不是一个值?
我可能遗漏了一些明显的东西,但非常感谢您的帮助
我从中获取此代码的脚本如下。我在调试器中逐步执行它,我可以在 sub gen_permutate
返回的最后一行中看到这种行为
my @DNA = qw/A C T G/;
my $seq = gen_permutate(14, @DNA);
while ( my $strand = $seq->() ) {
print "$strand\n";
}
sub gen_permutate {
my ($max, @list) = @_;
my @curr;
return sub {
if ( (join '', map { $list[ $_ ] } @curr) eq $list[ -1 ] x @curr ) {
@curr = (0) x (@curr + 1);
else {
my $pos = @curr;
while ( --$pos > -1 ) {
++$curr[ $pos ], last if $curr[ $pos ] < $#list;
$curr[ $pos ] = 0;
}
}
return undef if @curr > $max;
return join '', map { $list[ $_ ] } @curr;
};
}
J
我想回答我自己的问题,undef 有时被视为零。这就是 $list[undef] 与 $list[0]
相同的原因
这是“DWIM”的一部分——数组索引需要是一个数字,因此传入的内容将转换为一个,尽解释器所能做到的最好do/guess。在 undef
的情况下至少很清楚——变成了 0
.
但这确实是一个编程错误,或者至少是草率。
做你期望的事:
my @res = map { $list[ $_ ] } grep { defined } @curr;
或者,在列表的一次迭代中
my @res = map { defined $_ ? $list[$_] : () } @curr;
此处由 ()
表示的空列表被压平到 return 列表中,从而消失;所以我们也在 map
内部进行过滤。但是那个三元组的要点是能够代替有意义的东西,如果需要删除一些输入,那么先有一个明确的 grep
会更清楚。
注意 有了 use warnings;
你会听到所有关于它的信息
Use of uninitialized value $_ in array element at ...
(并将其转换为数字)
每个脚本确实必须以use warnings;
(和use strict;
)开头。有时继承旧脚本的最大部分是立即将 use warnings;
放在最上面(并处理满屏的消息 :(.
我很难理解下面 Perl 脚本中 map 函数的行为
my @list = qw/A C T G/;
my @curr = (0, undef, undef, 1);
my @res = map { $list[ $_ ] } @curr;
print @res; #prints AAAC
@res
的值为AAAC
。我原以为它只是 AC
因为 @curr
的 2 个中间值是 undef
.
我对map的理解是list中的每一项依次成为$_
的值。所以我可以理解 $list[0]
returns A 和 $list[1]
returns C。我无法理解 why/how undef
值返回了 A ?在我看来 $list[undef]
不是一个值?
我可能遗漏了一些明显的东西,但非常感谢您的帮助
我从中获取此代码的脚本如下。我在调试器中逐步执行它,我可以在 sub gen_permutate
my @DNA = qw/A C T G/;
my $seq = gen_permutate(14, @DNA);
while ( my $strand = $seq->() ) {
print "$strand\n";
}
sub gen_permutate {
my ($max, @list) = @_;
my @curr;
return sub {
if ( (join '', map { $list[ $_ ] } @curr) eq $list[ -1 ] x @curr ) {
@curr = (0) x (@curr + 1);
else {
my $pos = @curr;
while ( --$pos > -1 ) {
++$curr[ $pos ], last if $curr[ $pos ] < $#list;
$curr[ $pos ] = 0;
}
}
return undef if @curr > $max;
return join '', map { $list[ $_ ] } @curr;
};
}
J
我想回答我自己的问题,undef 有时被视为零。这就是 $list[undef] 与 $list[0]
相同的原因这是“DWIM”的一部分——数组索引需要是一个数字,因此传入的内容将转换为一个,尽解释器所能做到的最好do/guess。在 undef
的情况下至少很清楚——变成了 0
.
但这确实是一个编程错误,或者至少是草率。
做你期望的事:
my @res = map { $list[ $_ ] } grep { defined } @curr;
或者,在列表的一次迭代中
my @res = map { defined $_ ? $list[$_] : () } @curr;
此处由 ()
表示的空列表被压平到 return 列表中,从而消失;所以我们也在 map
内部进行过滤。但是那个三元组的要点是能够代替有意义的东西,如果需要删除一些输入,那么先有一个明确的 grep
会更清楚。
注意 有了 use warnings;
你会听到所有关于它的信息
Use of uninitialized value $_ in array element at ...
(并将其转换为数字)
每个脚本确实必须以use warnings;
(和use strict;
)开头。有时继承旧脚本的最大部分是立即将 use warnings;
放在最上面(并处理满屏的消息 :(.