【问题标题】:Can I pull the next element from within a Perl foreach loop?我可以从 Perl foreach 循环中提取下一个元素吗?
【发布时间】:2010-06-05 08:52:06
【问题描述】:

我可以在 Perl 中执行以下操作吗?

foreach (@tokens) {
     if (/foo/){
       # simple case, I can act on the current token alone
       # do something
       next;
    }
    if (/bar/) {
       # now I need the next token, too
       # I want to read/consume it, advancing the iterator, so that
       # the next loop iteration will not also see it
       my $nextToken = .....
       # do something
       next;
    }

}

更新:我在 Perl 中需要这个,但出于好奇:其他语言是否有简洁的语法?

【问题讨论】:

    标签: perl loops foreach


    【解决方案1】:

    您必须使用for 循环吗?复制原始文件并使用shift“使用”它:

    use strict;
    use warnings;
    
    my @original = 'a' .. 'z';    # Original
    my @array = @original;        # Copy
    
    while (my $token = shift @array) {
    
        shift @array if $token =~ /[nr]/; # consumes the next element
        print $token;
    }
    
    # prints 'abcdefghijklmnpqrtuvwxyz' ('s' and 'o' are missing)
    

    【讨论】:

    • 不错。在我的情况下,销毁原件甚至不是问题,所以我可以不用副本。
    【解决方案2】:

    不适用于foreach 循环。您可以使用 C 风格的 for 循环:

    for (my $i = 0; $i <= $#tokens; ++$i) {
      local $_ = $tokens[$i];
      if (/foo/){
         next;
      }
      if (/bar/) {
        my $nextToken = $tokens[++$i];
        # do something
        next;
      }
    }
    

    您也可以使用Array::Iterator 之类的内容。我将把那个版本留给读者作为练习。 :-)

    【讨论】:

      【解决方案3】:

      从 Perl 5.12 开始,each is now more flexible 还处理数组:

      use 5.012;
      use warnings;
      
      my @tokens = 'a' .. 'z';
      
      while (my ($i, $val) = each @tokens) {
          if ($val =~ m/[aeiou]/) {
              ($i, $val) = each @tokens;   # get next token after a vowel
              print $val;
          }
      }
      
      # => bfjpv
      


      each 的一个警告,记住迭代器是全局的,如果你跳出循环,它不会被重置。

      例如:

      while (my ($i, $val) = each @tokens) {
          print $val;
          last if $i == 12;
      }
      
      # => abcdefghijklm
      
      my ($i, $val) = each @tokens;
      say "Now at => $val ($i)";         # Now at => n (13)
      

      所以使用keysvalues手动重置迭代器:

      keys @tokens;                      # resets iterator
      ($i, $val) = each @tokens;
      say "Now at => $val ($i)";         # Now at => a (0)
      

      【讨论】:

      • 哇!我不知道——这会派上用场。谢谢你:)
      【解决方案4】:
          my $arr = [0..9];
      
          foreach ( 1 ..  scalar @{$arr} ) {
      
                 my $curr = shift @{$arr};
      
                 my $next = shift @{$arr};
      
                 unshift @{$arr} , $next;
      
                 print "CURRENT :: $curr :: NEXT :: $next \n";
          }
      

      【讨论】:

      • 这里的最佳解决方案。
      【解决方案5】:

      我喜欢 Zaids 的回答,但如果遇到数组中的 nul 元素,它会失败 所以...

      while (@array) {
      
          my $token = shift @array;
          shift @array if $token =~ /[nr]/; # consumes the next element
          print $token;
      } 
      

      直到@array 为空才会停止。

      【讨论】:

        猜你喜欢
        • 2011-07-03
        • 2013-05-17
        • 2021-08-25
        • 2022-06-29
        • 2011-06-13
        • 2020-04-10
        • 2019-09-14
        • 2016-06-11
        • 2020-11-24
        相关资源
        最近更新 更多