У меня есть файл CSV, который я использую split для анализа в массиве N элементов, где N кратно 3.
split
N
3
Есть ли способ, которым я могу сделать это
foreach my ( $a, $b, $c ) ( @d ) {}
похож на Python?
Я обратился к этой проблеме в моем модуле List :: Gen на 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 }
Вы также можете импортировать функцию mapn, которая используется List::Gen для реализации by:
mapn
List::Gen
by
use List::Gen qw/mapn/; mapn { # do something with the slices in @_ } 3 => @list;
Вы можете использовать List :: MoreUtils :: natatime .Из документов:
my @x = ('a' .. 'g'); my $it = natatime 3, @x; while (my @vals = $it->()) { print "@vals\n"; }
natatime реализовано в XS, поэтому вы должны отдать предпочтение его эффективностиПросто для иллюстрации, вот как можно реализовать трехэлементный генератор итераторов в Perl:
natatime
#!/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; } } }
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"; }
это выводит:
one two three four five six seven eight nine
@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"; }
производит:
1 2 3 4 5 6 7 8 9 0
не легко. Было бы лучше сделать @d массивом из трех элементов, поместив элементы в массив как ссылку на массив:
@d
foreach my $line (<>) push @d, [ split /,/, $line ];
(За исключением того, что вам действительно следует использовать один из модулей CSV из CPAN.