Get next element of array inside a foreach loop in perl without using next/skipping to next iteration of loop

10,582

You can use array indexes:

for my $i (0 .. $#lines) {
    # ...
    print $lines[$i];
    if (cond()) {
        $lines[ $i + 1 ] =~ s/pattern/replace/g;
    }
}

This will, however, process the "next" line again in the next iteration of the loop. If you do not want that, you can use the C-style for:

for (my $i = 0; $i < $#list ; $i++) {
    # ...
}

A more advanced technique would be to define an iterator:

#!/usr/bin/perl
use warnings;
use strict;


sub iterator {
    my $list = shift;
    my $i = 0;
    return sub {
        return if $i > $#$list;
        return $list->[$i++];
    }
}


my @list = qw/a b c d e f g h/;
my $get_next = iterator(\@list);

while (my $member = $get_next->()) {
    print "$member\n";
    if ('d' eq $member) {
        my $next = $get_next->();
        print uc $next, "\n";
    }
}
Share:
10,582
user806168
Author by

user806168

Updated on June 04, 2022

Comments

  • user806168
    user806168 7 months

    I am new to perl and am facing some problem in skipping to next element of an array inside a foreach loop without reiterating the loop. Suppose I have the following case where I am going through a array using a foreach loop.

     foreach (@lines){  
         ...  
         print "$_";     #print current line  
         if (cond){      #this condition is met by one "line" in @lines  
            #goto next line;  
            $_=~s/expr/substitute_expr/g;     #substitute in the next line  
          }  
         ...
     }
    

    Is it possible to do this in perl. With a file handler it is possible using the <> operator, as follows

    foreach $line (<FILE>){  
        print "$line\n";        #print this line  
        $line = <FILE>;  
        print "$line";        #print next line  
    } 
    

    Is there any way this can be replicated with an array.
    Is there any way to do this without using next or a duplicate array

  • mpapec
    mpapec over 9 years
    scalar @list - 1 is same as @list - 1 and as $#list
  • Ekkehard.Horner
    Ekkehard.Horner over 9 years
    @mpapec - as they are the same - why comment on my using the one I like best?
  • Jacob
    Jacob over 9 years
    Your for loop never iterates over the last element. If that is intended you should put a comment next to that line.
  • fbicknel
    fbicknel over 7 years
    I like that you used a closure in your iterator! Good solution: keeps the while loop neat and clear by keeping annoying indexes isolated in the iterator. Especially useful if you are parsing output and want to pull several lines from the "list" at intervals.
  • schulwitz
    schulwitz almost 7 years
    I like the closure iterator solution, but it's performance is unlike a normal foreach loop, in that it will unfortunately fail for any array element which is zero, an empty string, or undefined. I've posted an edited solution below.