Можно ли вытащить следующий элемент из цикла Perl foreach?
Можно ли сделать что-то вроде 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, но ради любопытства: на других языках есть опрятный синтаксис?
Ответы
Ответ 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
Начиная с Perl 5.12, каждый из них теперь более гибкий, также работая над массивами:
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
, помните, что итератор является глобальным и не является reset, если вы выходите из цикла.
Например,
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)
Поэтому используйте keys
или values
вручную reset итератор:
keys @tokens; # resets iterator
($i, $val) = each @tokens;
say "Now at => $val ($i)"; # Now at => a (0)
Ответ 3
Не с циклом foreach
. Вы можете использовать цикл for
C-стиля:
for (my $i = 0; $i <= $#tokens; ++$i) {
local $_ = $tokens[$i];
if (/foo/){
next;
}
if (/bar/) {
my $nextToken = $tokens[++$i];
# do something
next;
}
}
Вы также можете использовать что-то вроде Array::Iterator. Я оставлю эту версию в качестве упражнения для читателя.: -)
Ответ 4
Мне нравится ответ Zaids, но он терпит неудачу, если он встречает nul-элемент в массиве
так что...
while (@array) {
my $token = shift @array;
shift @array if $token =~ /[nr]/; # consumes the next element
print $token;
}
это не остановится, пока @array
не будет пустым.
Ответ 5
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";
}