2010-07-08 4 views
6

Ich habe eine CSV-Datei, die ich split verwenden, um in ein Array von N Elemente zu analysieren, wobei N ein Vielfaches von 3 ist.In Perl, wie kann ich über mehrere Elemente eines Arrays iterieren?

Gibt es eine Möglichkeit kann ich das tun

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

ähnlich wie Python?

+7

Sie eine nicht verwenden '$ 'und' $ b' für Variablennamen. Sie sind speziell gepackte Scope-Variablen zur Verwendung mit 'sort'. –

+0

Das wäre cool, wenn Sie das tun könnten. –

+0

Wenn Sie außerhalb der Sorte sind, ist es in Ordnung. Aber wenn es ein One-Liner ist, den du später wiederverwenden wirst, dann sei vorsichtig, richtig. :-) – eruciform

Antwort

12

können Sie List::MoreUtils::natatime verwenden Aus der Dokumentation.. 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; 
     } 
    } 
} 
+0

* n * zu einer Zeit - Ich mag es :-) – Mike

+0

heh lustig, wusste nicht darüber. wahrscheinlich ein Ein-Zeilen-Verschluss um Spleiß. :-) – eruciform

+1

@eruciform: in der Logik, ja, aber die Funktionen in List :: Util und List :: MoreUtils sind in XS für maximale Geschwindigkeit geschrieben.Es zahlt sich wirklich aus, genau die Funktion zu verwenden, die Sie benötigen, anstatt die eingebauten Funktionen zu verwenden, wenn Sie eine große Menge an Daten analysieren. – Ether

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

produziert:

1 2 3 
4 5 6 
7 8 9 
0 
+1

dies zerstört das '@ z' Array und ist wahrscheinlich besser als While-Schleife geschrieben –

+0

@eric: true. Dies ist eine schnelle Lösung. – eruciform

1

nicht leicht. Sie wäre besser dran @d ein Array aus drei Elementen bestehende Tupel zu machen, indem Sie die Elemente auf das Array als Array Referenz drängen:

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

(Außer, dass Sie sollten wirklich von CPAN einer der CSV-Module verwenden, hier ist

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

natatime in XS implementiert ist, so dass Sie es für Effizienz nur zu Veranschaulichungszwecken bevorzugen sollte, wie könnte man ein drei implementieren.

+0

thx, es ist für eine schnelle interne Hacks, didnt denke, es wäre so schwer – Timmy

14

ich adressiert dieses Problem in meinem Modul List::Gen auf 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 

} 

Sie auch die mapn Funktion importieren könnte, die von List::Gen verwendet wird by zu implementieren:

use List::Gen qw/mapn/; 

mapn { 

    # do something with the slices in @_ 

} 3 => @list; 
+0

sind sie tatsächlich Aliasing in einem "für mich"? oder nur in einer "for" -Schleife? das "mein" soll eine Kopie machen. geht das "um" herum? – eruciform

+2

Die Variable 'my' in einer Perl-foreach-Schleife ist niemals eine Kopie, sie ist immer ein Alias. Ein lexikalisch begrenzter Alias, aber trotzdem ein Alias. –

+3

Alles, was ich sagen kann, ist * sehr nett! * –

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

diese Ausgänge:

one two three 
four five six 
seven eight nine 
Verwandte Themen