【问题标题】:Elegant way to catch "for loop reached last element"?捕捉“for循环到达最后一个元素”的优雅方式?
【发布时间】:2018-12-21 22:31:27
【问题描述】:

有时在 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";
}

这将使这个测试更直观。

【问题讨论】:

  • for my $animal (@animals, "not $input") }... ;-)
  • 但是说真的,请使用来自List::Utilfirst
  • 哈哈,我喜欢第一个建议,但我一定会尝试first 的建议。像往常一样付费阅读文档。
  • if(grep(/$input/, @animals)){ true clause } else { equivalent of finally }

标签: for-loop foreach idioms perl


【解决方案1】:

你可以用这样的标签块包裹你的循环:

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";
}

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      只需让循环设置一个变量,这样您就可以检查它是否已设置并稍后采取行动:

      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";
      

      【讨论】:

        【解决方案4】:

        我会保留它的老派风格并使用著名的 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。

        【讨论】:

          【解决方案5】:

          首先是开销最小的; 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
          };
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-01-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-06-07
            • 2019-01-01
            • 1970-01-01
            • 2021-04-22
            相关资源
            最近更新 更多