2010-07-08 53 views
6

Tengo un archivo CSV que uso split para analizar en una matriz de N elementos, donde N es un múltiplo de 3.En Perl, ¿cómo puedo iterar sobre múltiples elementos de una matriz?

¿Hay alguna manera puedo hacer esto

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

similar a Python?

+7

No utilice '$ una 'y' $ b' para nombres de variables. Sus son variables de alcance especialmente empaquetadas para su uso con 'sort'. –

+0

Eso sería genial si pudiera hacer eso, sin embargo. –

+0

si está fuera de género, está bien. pero si es un trazador de líneas que vas a reutilizar, posiblemente de forma posterior, ten cuidado, es verdad. :-) – eruciform

Respuesta

12

puede utilizar List::MoreUtils::natatime a partir de los documentos:.

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

natatime se implementa en XS por lo que debe preferir que la eficiencia sólo para fines de ilustración, aquí es cómo se podría implementar un tres. generador de iterador elemento en 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 * a la vez - Me gusta :-) – Mike

+0

heh gracioso, no sabía de eso. probablemente un cierre de una línea alrededor del empalme. :-) – eruciform

+1

@eruciform: en lógica, sí, pero las funciones en List :: Util y List :: MoreUtils están escritas en XS para una velocidad máxima.Realmente vale la pena utilizar la función exacta que necesita en lugar de utilizar las funciones integradas al analizar una gran cantidad de datos. – 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"; 
} 

produce:

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

esto destruye la matriz '@ z' y probablemente está mejor escrito como un ciclo while –

+0

@eric: true. esta es una solución rápida. – eruciform

1
No

fácilmente. Usted sería mejor hacer @d un conjunto de tuplas de tres elementos, empujando los elementos en la matriz como una referencia a un array:

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

(Excepto que realmente debe utilizar uno de los módulos de CPAN CSV .

+0

thx, es para unos ataques internos rápidos, no pensé que sería tan difícil – Timmy

14

que abordó esta cuestión en mi módulo List::Gen en 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 

} 

También puede importar la función mapn, que es utilizado por List::Gen para implementar by:

use List::Gen qw/mapn/; 

mapn { 

    # do something with the slices in @_ 

} 3 => @list; 
+0

¿son realmente alias en un "para mi"? o simplemente en un bucle "para"? el "mi" se supone que debe hacer una copia. ¿"por" evitar esto? – eruciform

+2

la variable 'my' en un bucle foreach de Perl nunca es una copia, siempre es un alias. Un alias de ámbito léxico, pero sin embargo un alias. –

+3

Todo lo que puedo decir es * ¡muy agradable! * –

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

Muestra esto:

one two three 
four five six 
seven eight nine 
Cuestiones relacionadas