Tutorial :In Perl, how can I iterate over multiple elements of an array?



Question:

I have a CSV file that I use split to parse into an array of N items, where N is a multiple of 3.

Is there a way i can do this

foreach my ( $a, $b, $c ) ( @d ) {}  

similar to Python?


Solution:1

You can use List::MoreUtils::natatime. From the docs:

my @x = ('a' .. 'g');  my $it = natatime 3, @x;  while (my @vals = $it->()) {      print "@vals\n";  }  

natatime is implemented in XS so you should prefer it for efficiency. Just for illustration purposes, here is how one might implement a three element iterator generator in Perl:

#!/usr/bin/perl    use strict; use warnings;    my @v = ('a' .. 'z' );    my $it = make_3it(\@v);    while ( my @tuple = $it->() ) {      print "@tuple\n";  }    sub make_3it {      my ($arr) = @_;      {          my $lower = 0;          return sub {              return unless $lower < @$arr;              my $upper = $lower + 2;              @$arr > $upper or $upper = $#$arr;              my @ret = @$arr[$lower .. $upper];              $lower = $upper + 1;              return @ret;          }      }  }  


Solution:2

I addressed this issue in my module List::Gen on CPAN.

use List::Gen qw/by/;    for my $items (by 3 => @list) {        # do something with @$items which will contain 3 element slices of @list        # unlike natatime or other common solutions, the elements in @$items are      # aliased to @list, just like in a normal foreach loop    }  

You could also import the mapn function, which is used by List::Gen to implement by:

use List::Gen qw/mapn/;    mapn {       # do something with the slices in @_    } 3 => @list;  


Solution:3

@z=(1,2,3,4,5,6,7,8,9,0);    for( @tuple=splice(@z,0,3); @tuple; @tuple=splice(@z,0,3) )   {     print "$tuple[0] $tuple[1] $tuple[2]\n";   }  

produces:

1 2 3  4 5 6  7 8 9  0  


Solution:4

my @list = (qw(one two three four five six seven eight nine));    while (my ($m, $n, $o) = splice (@list,0,3)) {    print "$m $n $o\n";  }  

this outputs:

one two three  four five six  seven eight nine  


Solution:5

Not easily. You'd be better off making @d an array of three-element tuples, by pushing the elements onto the array as an array reference:

foreach my $line (<>)      push @d, [ split /,/, $line ];  

(Except that you really ought to use one of the CSV modules from CPAN.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »