2010-07-08 93 views
6

我有一个CSV文件,我使用split来解析N项目的数组,其中N3的倍数。在Perl中,我如何迭代数组的多个元素?

有没有一种方法,我可以做到这一点

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

类似的Python?

+7

不要使用'$一个'和'$ b'作为变量名称。它们是与'sort'一起使用的专门打包的范围变量。 – 2010-07-08 22:22:48

+0

虽然,如果你可以这样做,那将会很酷。 – 2010-07-08 22:28:06

+0

如果你在外面,那很好。但是如果它是一行一行的话,你可能会稍后重复使用,那么请小心,确实如此。 :-) – eruciform 2010-07-08 22:39:34

回答

12

您可以使用List::MoreUtils::natatime从文档:

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

natatime在XS实现的,所以你应该更喜欢它的效率仅用于演示,这里是一个如何可能实现三。在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; 
     } 
    } 
} 
+0

* n *在某一时间 - 我喜欢它:-) – Mike 2010-07-08 22:30:03

+0

heh有趣,不知道那一个。可能是拼接的单线封闭。 :-) – eruciform 2010-07-08 22:36:12

+1

@eruciform:在逻辑中,是的,但List :: Util和List :: MoreUtils中的函数是以XS写入的,以获得最大速度。在分析大量数据时,它确实会付出代价来使用所需的确切函数,而不是使用内置函数。 – Ether 2010-07-08 22:43:47

4
@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 
+1

这破坏了@ z'数组,并可能更好地写成一个while循环 – 2010-07-08 22:41:29

+0

@eric:true。这是一个快速解决方案。 – eruciform 2010-07-08 22:48:20

1

不容易。你会推迟作出@d三元素的元组的阵列,通过推动元素到数组的数组引用更好:

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

(除非你真的应该使用来自CPAN的CSV模块之一。

+0

thx,这是一个快速的内部黑客,没想到它会如此艰难 – Timmy 2010-07-08 22:17:46

14

我我的CPAN模块List::Gen在解决了这个问题。

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

use List::Gen qw/mapn/; 

mapn { 

    # do something with the slices in @_ 

} 3 => @list; 
+0

他们实际上在别人的“为我”?或者只是在“for”循环中? “我的”应该做一个副本。 “通过”解决这个问题? – eruciform 2010-07-08 22:37:28

+2

Perl foreach循环中的'my'变量绝不是副本,它始终是别名。一个词法范围的别名,但别名更少。 – 2010-07-08 22:39:08

+3

我只能说*非常好!* – 2010-07-08 22:48:12

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

此输出:

one two three 
four five six 
seven eight nine 
相关问题