如何将条件和循环放在同一行中?
How do I put a conditional and a loop in the same line?
我想在 Perl 的同一行上放置条件和循环。这就是我想要实现的目标:
foreach (0 .. 10) {
print $_ if $_ % 2;
}
应该给我 13579
。我在 Python 中寻找类似循环理解的语句,例如
[i for i in range(10) if i % 2]
我知道 print $_ foreach 0 .. 10;
有效,但问题是也将条件添加到语句中...
Perl 不是 Python。列表理解很好,但 Perl 没有。
最接近的 perl 习语可能类似于
grep $_ % 2 , (0..9);
试用 1 线:
$ perl -e '@a = grep $_ % 2 , (0..9); print "@a\n"'
1 3 5 7 9
请注意,内存和时间可能存在性能差异。我很确定 Perl 会构建包含 10 个项目的完整列表并过滤它以生成一个新列表。列表理解可以直接构建过滤列表。
对于奇数的列表元素
$_%2 and print for 0..10;
或
$_&1 and print for 0..10;
或者可能需要奇数索引处的元素,其中 0..10
代表数组索引
my @ary = 0..10;
$_&1 and print $ary[$_] for 0..$#ary;
语法$#ary
是数组@ary
的最后一个元素的索引。
关键是 Perl 的 and
short-circuits 所以如果它的 left-hand-side 上的表达式不正确那么它的 right-hand-side 上的内容就不会 运行。 (与 or
相同——如果 LHS 为真,则不评估 RHS。)
如果确实需要奇数索引的数组元素也可以
my @ary = 0..10;
print for @ary[grep { $_&1 } 0..$#ary];
以上全部打印13579
(无换行)。在one-liner,进入运行command-line
perl -we'$_%2 and print for 0..10'
如果你真的需要在自己的行上打印每个数字,根据发布的评论判断,将 print
替换为 say
,如
$_%2 and say for 0..$#ary;
对于数组 @ary
中的奇数数组元素,或
$_&1 and say $ary[$_] for 0..$#ary;
对于奇数索引处的数组元素。
将 use feature 'say';
添加到程序的开头(除非它已被其他加载的 tools/libraries 启用)。
为什么不像下面这样?
use warnings;
use strict;
print ($_ % 2 ? $_ : "") for (1..10);
如果你想建立一个特定的列表,你总是可以使用经典的 c-style for loop。另外,如果你想把它“放在一行”,你可以把它塞进一行。 Perl 不是 Python,对换行或缩进没有要求。但是,将代码放在一行会降低可读性。
for (my $i = 1; $i <= 10; $i += 2) { print $i; }
您不必以这种方式构建列表并删除其中的一半。可能会有一些性能差异,您可以随时对它进行基准测试,但对我来说它闻起来像是过早的优化。
就此而言,如果您愿意,您也可以使用相同的逻辑使用 while
循环。
my $i = 1; while ($i <= 10) { print $i; $i += 2; }
一般答案是使用grep
。
say for grep $_ % 2, 0..10;
作为 case-specific 解决方案,您可以使用以下方法:
say $_ * 2 for 0..5;
我想在 Perl 的同一行上放置条件和循环。这就是我想要实现的目标:
foreach (0 .. 10) {
print $_ if $_ % 2;
}
应该给我 13579
。我在 Python 中寻找类似循环理解的语句,例如
[i for i in range(10) if i % 2]
我知道 print $_ foreach 0 .. 10;
有效,但问题是也将条件添加到语句中...
Perl 不是 Python。列表理解很好,但 Perl 没有。
最接近的 perl 习语可能类似于
grep $_ % 2 , (0..9);
试用 1 线:
$ perl -e '@a = grep $_ % 2 , (0..9); print "@a\n"'
1 3 5 7 9
请注意,内存和时间可能存在性能差异。我很确定 Perl 会构建包含 10 个项目的完整列表并过滤它以生成一个新列表。列表理解可以直接构建过滤列表。
对于奇数的列表元素
$_%2 and print for 0..10;
或
$_&1 and print for 0..10;
或者可能需要奇数索引处的元素,其中 0..10
代表数组索引
my @ary = 0..10;
$_&1 and print $ary[$_] for 0..$#ary;
语法$#ary
是数组@ary
的最后一个元素的索引。
关键是 Perl 的 and
short-circuits 所以如果它的 left-hand-side 上的表达式不正确那么它的 right-hand-side 上的内容就不会 运行。 (与 or
相同——如果 LHS 为真,则不评估 RHS。)
如果确实需要奇数索引的数组元素也可以
my @ary = 0..10;
print for @ary[grep { $_&1 } 0..$#ary];
以上全部打印13579
(无换行)。在one-liner,进入运行command-line
perl -we'$_%2 and print for 0..10'
如果你真的需要在自己的行上打印每个数字,根据发布的评论判断,将 print
替换为 say
,如
$_%2 and say for 0..$#ary;
对于数组 @ary
中的奇数数组元素,或
$_&1 and say $ary[$_] for 0..$#ary;
对于奇数索引处的数组元素。
将 use feature 'say';
添加到程序的开头(除非它已被其他加载的 tools/libraries 启用)。
为什么不像下面这样?
use warnings;
use strict;
print ($_ % 2 ? $_ : "") for (1..10);
如果你想建立一个特定的列表,你总是可以使用经典的 c-style for loop。另外,如果你想把它“放在一行”,你可以把它塞进一行。 Perl 不是 Python,对换行或缩进没有要求。但是,将代码放在一行会降低可读性。
for (my $i = 1; $i <= 10; $i += 2) { print $i; }
您不必以这种方式构建列表并删除其中的一半。可能会有一些性能差异,您可以随时对它进行基准测试,但对我来说它闻起来像是过早的优化。
就此而言,如果您愿意,您也可以使用相同的逻辑使用 while
循环。
my $i = 1; while ($i <= 10) { print $i; $i += 2; }
一般答案是使用grep
。
say for grep $_ % 2, 0..10;
作为 case-specific 解决方案,您可以使用以下方法:
say $_ * 2 for 0..5;