捕捉“ for循环到达最后一个元素”的优雅方法?

时间:2018-12-21 22:31:27

标签: perl for-loop foreach idioms perl5

有时在Perl中,我编写了一个for / foreach循环,该循环遍历值以对照列表检查值。第一次命中后,就可以退出循环,因为我们已经满足了我的测试条件。例如,以下简单代码:

my @animals = qw/cat dog horse/;

foreach my $animal (@animals)
{
  if ($input eq $animal)
  {
    print "Ah, yes, an $input is an animal!\n";
    last;
  }
}
# <-----

有没有一种优雅的方法-可能是一个重载的关键字-处理“ for循环到达最后一个元素”?在上方的箭头上放些东西了吗?

我可以想到实现此目的的方法,例如创建/设置其他$found变量并在末尾对其进行测试。...但是我希望Perl可以内置其他东西,例如:

foreach my $animal (@animals)
{
  if ($input eq $animal)
  {
    print "Ah, yes, an $input is an animal!\n";
    last;
  }
} finally {
  print "Sorry, I'm not sure if $input is an animal or not\n";
}

这将使测试更加直观。

5 个答案:

答案 0 :(得分:3)

您可以像这样用标记块包装循环:

outer: {
    foreach my $animal (@animals) {
        if ($input eq $animal) {
            print "Ah, yes, an $input is an animal!\n";
            last outer;
        }
    }
    print "no animal found\n";
}

答案 1 :(得分:2)

这不是最好的解决方案,但有时它有助于迭代索引。

for my $i (0..$#animals) {
    my $animal = $animals[$i];
    ...
}

然后,您可以检查索引是0(第一遍)还是$#a(最后一遍)。

答案 2 :(得分:1)

只需在循环中设置一个变量,以便您可以检查它是否已设置并稍后对其进行操作:

my $found;
foreach my $animal (@animals) {
    if ($input eq $animal) {
        $found = $animal;
        last outer;
    }
}
print defined $found ? "Ah, yes, an $input is an animal!\n" : "no animal found\n";

但是对于这个特殊的问题,如@choroba所说,只需使用List :: Util中的first(或any)函数。或者,如果您要检查大量输入,则检查散列会更容易。

my %animals = map { ($_ => 1) } qw/cat dog horse/;
print exists $animals{$input} ? "Ah, yes, an $input is an animal!\n" : "no animal found\n";

答案 3 :(得分:1)

我将其保留为Old School,并使用一个众所周知的C惯用法(在第一个语句中分割for循环,在while循环中分割)。

#!/usr/bin/env perl

use strict;
use warnings;

my $input = 'lion';

my @animals = qw/cat dog horse/;

my $index = 0;

while ($index < scalar @animals) {
    if ($animals[ $index++ ] eq $input) {
        print "Ah, yes, an $input is an animal!\n";
        last;
    }
}

if ($index == scalar @animals) {
    print "Sorry, I'm not sure if $input is an animal or not\n";
}

因此,“对不起,我不确定狮子是否是动物”会很自然地出现。 希望这可以帮助。问候,M。

答案 4 :(得分:1)

首先将是最少的开销; eval避免将所有内容嵌套在if块中;换行符,因为您可能并不十分在意这行不是动物。

eval
{
  my $found = first { check for an animal } @animalz
  or die "Sorry, no animal found.\n";

  # process an animal

  1
}
// do
{
  # deal with non-animals
};