una print matriz lenguaje funcion ejemplos definir crear arreglo array perl loops

matriz - print array perl



¿Cómo leo dos elementos a la vez en un bucle foreach de Perl? (18)

Configure algunos datos de prueba e indique:

use Modern::Perl; use List::AllUtils qw''zip''; my @array = zip @{[''a''..''z'']}, @{[1..26]} ;

Bucle simple usando una variable de incremento.

{ my $i = 0; while( (my($a,$b) = @array[$i++,$i++]), $i <= @array # boolean test ){ say "$a => $b"; } }

Looping sobre pares usando List::Pairwise (pair) .

use List::Pairwise qw''pair''; for my $pair (pair @array){ my($a,$b) = @$pair; say "$a => $b"; }

Looping sobre la matriz 2 a la vez, usando List::MoreUtils (natatime) .

use List::AllUtils qw''natatime''; my $iter = natatime 2, @array; while( my($a,$b) = $iter->() ){ say "$a => $b"; }

Forzarlo en un hash, y recorrer las teclas. Útil si no te importa el orden.

{ my %map = @array; for my $key (keys %map){ my $value = $map{$key}; say "$key => $value"; } }

Lo que estoy buscando es algo así como:

@list = qw(1 2 3 4 5 6); foreach (@list) { #perl magic goes here print "i: $i, j:$j/n"; }

devoluciones:

i:1, j:2 i:3, j:4 i:5, j:6

En respuesta a una muy buena sugerencia a continuación, debo especificar que este script se ejecutará en el servidor de compilación de otra persona, y no puedo usar ningún módulo de CPAN. Solo Perl estándar.


¿Qué tal una solución funcional de propósito general?

use Carp; # so mapn can croak about errors sub mapn (&$@) { my ($sub, $n, @ret) = splice @_, 0, 2; croak ''$_[1] must be >= 1'' unless $n >= 1; while (@_) { local *_ = /$_[0]; push @ret, $sub->(splice @_, 0, $n) } @ret } sub by ($@) {mapn {[@_]} shift, @_} sub every ($@); *every = /&by;

La función mapn funciona igual que map , excepto que el primer argumento después de su bloque es la cantidad de elementos a tomar. Coloca el primer elemento en $_ y todos los elementos en @_ .

print mapn {"@_/n"} 2 => 1 .. 5; # prints 1 2 3 4 5

Los siguientes dos subs idénticos, by y every crean adverbios útiles para las diversas construcciones de bucle. Procesan la lista con mapn y devuelven una lista de referencias de matriz del tamaño deseado

print "@$_/n" for every 2 => 1..10; print map {"@$_/n"} grep {$_->[1] > 5} by 2 => 1..10;

Encuentro que esta es una solución más limpia e intuitiva que natatime, u otras soluciones únicas como el estilo de CA para loop.


Arriesgando la etiqueta de nigromancia, decidí agregar una más de la mochila de Tim Toady:

for (0 .. $#list) { next if $_ % 2; my ($i, $j) = @list[$_, $_ + 1]; say "i:$i, j:$j"; }

No destructivo, sin listas duplicadas, sin variables de estado y razonablemente concisa.


Como explica Mirod, no hay mucho código para eso. Aquí hay prácticamente todo lo que necesitarías. (Tenga en cuenta que no tengo ningún control para las listas impares o similares).

#!/usr/bin/env perl use strict; use warnings; my @list = qw/1 2 3 4 5 6/; my $get_em = get_by(2, @list); while ( my ($i, $j) = $get_em->() ) { print "i: $i, j: $j/n"; } sub get_by { my $n = shift; my @list = @_; return sub { return splice @list, 0, $n; } }


Creé este código para resolver un requisito similar:

sub map_pairs(&/@) { my $op = shift; use vars ''@array''; local *array = shift; # make alias of calling array return () unless @array; # Get package global $a, $b for the calling scope my ($caller_a, $caller_b) = do { my $pkg = caller(); no strict ''refs''; /*{$pkg.''::a''}, /*{$pkg.''::b''}; }; # Get index counter size. my $limit = $#array/2; # Localize caller''s $a and $b local(*$caller_a, *$caller_b); # This map is also the return value map { # assign to $a, $b as refs to caller''s array elements (*$caller_a, *$caller_b) = /($array[$_], $array[$_+1]); $op->(); # perform the transformation } map { 2 * $_ } 0..$limit; # get indexes to operate upon. }

Lo usas así:

@foo = qw( a 1 b 2 c 3 ); my @bar = map_pairs { "$a is $b" } @foo;

Llegar:

@bar = ( ''a is 1'', ''b is 2'', ''c is 3'' );

He querido enviar al mantenedor de List :: MoreUtils, pero no tengo una versión XS para ofrecer.


Creo que la forma correcta de hacerlo es usar tiempo nata, de List::MoreUtils :

de los documentos:

natatime LISTA DE BLOQUES

Crea un iterador de matriz, para recorrer una matriz en fragmentos de $n elementos a la vez. ( n a la vez, ¿entiendes?). Un ejemplo es probablemente una mejor explicación de la que podría dar en palabras.

Ejemplo:

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

Esto imprime

a b c d e f g

La implementación de List::MoreUtils::natatime :

sub natatime ($@) { my $n = shift; my @list = @_; return sub { return splice @list, 0, $n; } }


Creo que querrías hacer esto de otra manera. Prueba esto:

while (scalar(@list) > 0) { $i = shift(@list); $j = shift(@list); print "i: $i, j:$j/n"; }

Tenga en cuenta que esto destruirá la lista, pero funcionará para ese pequeño bucle.


El equivalente más cercano es, desafortunadamente, ir a la vieja escuela:

for(my $ix = 0; $ix <= $#list; $ix += 2) { my $i = $list[$ix]; my $j = $list[$ix + 1]; print "i: $i, j:$j/n"; }

Me gusta más la respuesta de Jack M, realmente, aunque la escribiría en Perl, más sexy:

while(@list) { my $i = shift @list; my $j = shift @list; print "i: $i, j:$j/n"; }


Es probable que desee crear una subrutina simple para que funcione para usted.

Sugiero esto:

{ my $cl_ind = 0; sub arrayeach(@) { my @obj = @_; if(($cl_ind+2) > @obj) { $cl_ind = 0; return; } $cl_ind+=2; return ($obj[$cl_ind-2],$obj[$cl_ind-1]); } }

El cierre lo hace funcionar limpiamente. Para usar arrayeach (que funciona como hash cada uno sin requerir una coerción peligrosa a una matriz:

my @temp = (1,2,3,4,5,6,1,2,3,4,5,6); while( ($a,$b) = arrayeach(@temp)) { print "A $a AND $b/n"; }

Esto no es destructivo


Esto se puede hacer de forma no destructiva, con List::Gen simplemente fantástica de List::Gen :

perl -MList::Gen=":utility" -E ''@nums = "1" .. "6" ; say "i:$_->[0] j:$_->[1]" for every 2 => @nums''

Salida :

i:1 j:2 i:3 j:4 i:5 j:6

Editar (agregue una versión sin CPAN):

Array slices y C-style para loop à la brian d foy y Tom Christiansen ! Esto se puede leer como "usar un índice ( $i ) para recorrer un @list foreach $n elementos a la vez":

use v5.16; # for strict, warnings, say my @list = "1" .. "6"; my $n = 2 ; # the number to loop by $n-- ; # subtract 1 because of zero index foreach (my $i = 0 ; $i < @list ; $i += $n ) { say "i:", [ @list[$i..$i+$n] ]->[0], " j:", [ @list[$i..$i+$n] ]->[1]; $i++ ; }

Accedemos a los resultados como elementos ( ->[0] ) de una matriz anónima ( [ ] ). Para un resultado más genérico, la porción de matriz interpolada se puede usar por sí misma, por ejemplo : print "@list[$i..$i+$n]"; cambiando el valor de $n según sea necesario.


Si solo pudiera usar Perl estándar sin módulos, probablemente bajaría a un estilo C para el ciclo que cuenta por 2:

for( my $i = 0; $i < @array; $i += 2 ) { my( $i, $j ) = @array[ $i, $i+1 ]; ... }

Sin embargo, si quiere algo sofisticado de uno de los módulos que no puede usar, simplemente puede agregar ese módulo a su código. Si puedes escribir código, puedes usar módulos. Puede que tenga que incluir el módulo con todo el código que entrega mientras configura adecuadamente @INC . Esta es la idea básica de inc::Module::Install y PAR .

Paso mucho tiempo trabajando con un sistema de compilación que crea su propio repositorio CPAN, instala sus dependencias desde su CPAN privado y luego prueba el código. Tener una granja de compilación no impide el uso de módulos; es la política local lo que hace. Sin embargo, eso podría no tener sentido en todos los casos, aunque sea posible.


Usar un bucle for hará lo que necesites.

use strict; use warnings; my @list = qw(1 2 3 4 5 ); my $i = 0; for ($i = 0; $i < scalar(@list); $i++) { my $a = $list[$i]; my $b = $list[++$i]; if(defined($a)) { print "a:$a"; } if(defined($b)) { print "b:$b"; } print "/n"; }

editar : Corregí mi publicación para usar la función escalar para recuperar el tamaño de la matriz y también agregar algunas comprobaciones en caso de que la matriz no contenga un número par de elementos.


Yo usaría empalme.

my @list = qw(1 2 3 4 5 6); while(my ($i,$j) = splice(@list,0,2)) { print "i: $i, j: $j/n"; }


aquí hay una implementación de natatime que no hace una copia de la lista:

sub natatime { my $n = shift; my $list = /@_; sub { return splice @$list, 0, $n; } } my $it = natatime(3, qw(1 2 3 4 5 6)); while ( my @list = $it->() ) { print "@list/n"; }


otro enfoque, no totalmente limpio, pero utilizable. cada uno crea un iterador, puede usarlo dos veces. cuando el parámetro es una matriz clásica, devuelve índice y valor, lea esto: https://perldoc.perl.org/functions/each.html

Entonces, tu código puede ser así:

my @array=qw(one two three four five); #five element as unpaired will be ignored while (my ($i1,$one,$i2,$two)=(each(@array),each(@array)) { #we will use $ix for detect end of array next unless defined $i1 and defined $i2; #secure complete end of array print "fetched array elements: $one => $two/n"; };

El ejemplo anterior no destruirá los datos de origen, contra desplazamiento o similar. Espero que esto sea útil para cualquiera. por supuesto, el caso con iterador simple es mucho mejor.


solución rápida para matrices pequeñas:

for ( map {$_*2} 0..@list/2-1 ){ my ($i, $j) = @list[$_,$_+1]; print "i: $i, j:$j/n"; }

algún tipo de oneliner

datos:

@v = (a=>1, b=>2, c=>3);

esta

print join '', '', map{sprintf ''%s:%s'', $v[$_], $v[$_+1]} grep {!($_%2)} 0..$#v

o algo así como esto

print join '', '', map {sprintf ''%s:%s'', @v[$_,$_+1]} map {$_*2} 0..@v/2-1;

el resultado es el mismo

a:1, b:2, c:3


Creo que una forma más simple es usar viejos pobres ''cada''. Directamente como esto:

while (my ($key,$value) = each @list) { print "$key=$value/n"; }

Actualizado:

Sí, está mal. Uno debería convertir la lista al hash primero, pero podría ser demasiado explícito:

my %hash = (@list); while (my ($key,$value) = each %hash) { print "$key=$value/n"; }


my $i; for ( qw(a b c d) ) { if (!defined($i)) { $i = $_; next; } print STDOUT "i = $i, j = $_/n"; undef($i); }

Productos:

i = a, j = b i = c, j = d

También funciona para listas, no solo para matrices.