2010-06-05 40 views
12

Tôi có thể làm điều gì đó như sau trong Perl không?Tôi có thể kéo phần tử tiếp theo từ trong vòng lặp Perl foreach không?

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

} 

Cập nhật: tôi cần điều này trong Perl, nhưng vì lợi ích của sự tò mò của: Do các ngôn ngữ khác có một cú pháp gọn gàng cho điều đó?

Trả lời

19

Bạn có sử dụng vòng lặp for không? Sao chép bản gốc và 'tiêu thụ' nó với 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) 
+0

Tốt. Trong trường hợp của tôi, phá hủy bản gốc thậm chí không phải là một vấn đề, vì vậy tôi có thể làm mà không có bản sao. – Thilo

8

Không có vòng lặp foreach. Bạn có thể sử dụng một C-style for loop:

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

Bạn cũng có thể sử dụng giống như Array::Iterator. Tôi sẽ để lại phiên bản đó như một bài tập cho người đọc. :-)

9

Bắt đầu với Perl 5,12, each is now more flexible bởi cũng làm việc trên mảng:

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 


Một caveat với each, nhớ iterator là toàn cầu và không được đặt lại nếu bạn thoát khỏi vòng lặp.

Đối với ví dụ:

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) 

Vì vậy, sử dụng keys hoặc values tự thiết lập lại các iterator:

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

Whoa! Tôi không biết - điều này sẽ có ích. Cảm ơn bạn :) – zdim

0

Tôi thích Zaids câu trả lời nhưng nó không thành công nếu nó gặp một yếu tố nul trong mảng nên ...

while (@array) { 

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

điều này sẽ không sto p cho đến khi @array trống.

Các vấn đề liên quan