如何将条件和循环放在同一行中?

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;