在Perl的foreach循环中,我能否获取下一个元素?

12

我能在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 实现这个,但出于好奇,其他编程语言是否有类似的简洁语法呢?

5个回答

20

你一定要使用 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)

很好。在我的情况下,销毁原始数据甚至不是一个问题,所以我可以不用复制。 - Thilo

10

不能使用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的东西。我会把这个版本留给读者作为练习。 :-)

9

从Perl 5.12开始,each现在更加灵活,也可以用于数组:

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)

哇!我不知道——这会很方便。谢谢 :) - zdim

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

最佳解决方案在这里。 - Ilan Kleiman

0

我喜欢Zaid的答案,但如果在数组中遇到空元素,则会失败...

while (@array) {

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

直到@array为空,这个程序不会停止。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接