2010-07-08 47 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 
相關問題