2009-05-04 12 views
8

Necesito crear un archivo de texto (aptest.s) que puedo usar para leer en otro programa. Estoy usando Perl porque tengo una gran lista para trabajar. Mi código es el siguiente (que no da la salida deseada, se muestra después del código y la salida real). Cualquier ayuda sería apreciada.¿Cómo puedo iterar sobre varias listas al mismo tiempo en Perl?

#!/usr/bin/perl -w 
chdir("D://projects//SW Model ODME"); 
@link = ("319-116264||319-118664","320-116380||320-116846","321-119118||321-119119","322-115298||322-119087"); 
@link1 = ("116264-319||118664-319","116380-320||116846-320","119118-321||119119-321","115298-322||119087-322"); 
open (FSAS, ">>aptest.s"); 
foreach $link (@link) { 
    foreach $link1 (@link1){ 
    print FSAS "other code \n"; 
    print FSAS "PATHLOAD SELECTLINK=(Link=".$link."), VOL[2]=MW[1] \n"; 
    print FSAS "PATHLOAD SELECTLINK=(Link=".$link1."), VOL[3]=MW[2] \n"; 
    print FSAS "other code \n"; 
} 
} 

Salida Real:

other output 
PATHLOAD SELECTLINK=(Link=319-116264||319-118664), VOL[2]=MW[1] 
PATHLOAD SELECTLINK=(Link=116264-319||118664-319), VOL[3]=MW[2] 
other output 

other output 
PATHLOAD SELECTLINK=(Link=**319-116264||319-118664**), VOL[2]=MW[1] 
PATHLOAD SELECTLINK=(Link=**116380-320||116846-320**),  VOL[3]=MW[2] 
other output 

salida deseada

other output 
PATHLOAD SELECTLINK=(Link=319-116264||319-118664), VOL[2]=MW[1] 
PATHLOAD SELECTLINK=(Link=116264-319||118664-319), VOL[3]=MW[2] 
other output 

other output 
PATHLOAD SELECTLINK=(Link=**320-116380||320-116846**), VOL[2]=MW[1] 
PATHLOAD SELECTLINK=(Link=**116380-320||116846-320**), VOL[3]=MW[2] 
other output 

Respuesta

0

se puede reducir el tamaño de los datos de código y de ejemplo al mismo tiempo que reproduce el error? No puedo ver de inmediato la diferencia entre el producto real y el esperado.

A veces, encontrar un conjunto mínimo de código y datos que causa un problema hará que la solución sea obvia.

Mirando un poco más de cuidado, sólo hay un poco de código de salida que es variable:

print FSAS "PATHLOAD PATH=TIME, MW[1]=MI.1.1, SELECTLINK=(Link=".$link."), VOL[2]=MW[1] \n"; 
print FSAS "PATHLOAD PATH=TIME, MW[2]=MI.1.1, SELECTLINK=(Link=".$link1."), VOL[3]=MW[2] \n"; 

Su error es probable que sea allí.

+0

Gracias a todos por sus comentarios y sugerencias. He hecho que mi código sea más legible y agradezco su opinión. – Krishnan

20

Ver each_array en List::MoreUtils:

#!/usr/bin/perl 

use strict; 
use warnings; 

use List::MoreUtils qw(each_array); 

my @x = qw(A B C D E F); 
my @y = (10, 11, 12, 13, 14, 15); 

my $it = each_array(@x, @y); 
while (my ($x, $y) = $it->()) { 
    print "$x = $y\n"; 
} 
__END__ 
+0

Sí. Eso es probablemente lo que el interlocutor necesita. –

4

I piensan que estamos tratando de crear cuatro bloques separados, con cada elemento de la matriz link asociado con el elemento correspondiente de la matriz link2 ?

Sin embargo en realidad estás salida dieciséis bloques, uno para cada combinación de link y link1.

en lugar de tratar:

foreach $i (0 .. $#link) { 

    $link = $link[$i]; 
    $link1 = $link1[$i]; 

    ... 
} 
2

La lectura de su pregunta, que era difícil decir lo que realmente quería saber. Creo que Sinan Unur es correcto y que desea iterar simultáneamente en dos arreglos. Como él dice, List :: MoreUtils proporciona la muy útil función each_array().

También es fácil de iterar en una o más matrices por índice.

Puede generar una lista de índices para usar con un ciclo for normal. Esto usa $# para obtener el índice del último valor en la matriz.

for (0..$#array) { ... } 

O puede utilizar un C-estilo para el bucle para generar sus índices. Esto utiliza el hecho de que una matriz evaluada en contexto escalar devuelve la cantidad de elementos.

for (my $i=0; $i<@array; $i++) { ... } 

También podría escribirse usando $#:

for (my $i=0; $i<=$#array; $i++) { ... } 

Tras la lectura de su código, estaba claro que no está familiarizado con Perl's quoting operators. Su uso eficaz hace que sus scripts sean mucho más fáciles de escribir y leer.

En un espíritu amable, por favor, que me permita poner en orden la secuencia de comandos:

#!/usr/bin/perl 

# Always: 
use strict; 
use warnings; 

#my $TARGET_DIR = 'D://projects//SW Model ODME'; 
my $TARGET_DIR = '.'; 

my $TARGET_FILE = 'aptest.s'; 

# Using qw() makes long lists of 
# literals easier to type and read. 
# Consider finding better names than link and link1. 
# Something that describes the relationship between 
# the two arrays. 
my @link = qw(
    319-116264||319-118664 
    320-116380||320-116846 
    321-119118||321-119119 
    322-115298||322-119087 
); 

my @link1 = qw(
    116264-319||118664-319 
    116380-320||116846-320 
    119118-321||119119-321 
    115298-322||119087-322 
); 

# check the results of chdir. 
chdir($TARGET_DIR) 
    or die "Unable to enter $TARGET_DIR - $!\n"; 

# Use a lexical filehandle. 
# Use 3 arg open 
# Check the results of open - you need to know if it fails. 
open (my $fsas, '>>', $TARGET_FILE) 
    or die "Unable to open $TARGET_FILE - $!\n"; 

# Verify that the link arrays are both sized appropriately. 
die "Link arrays are not the same size." 
    unless @link == @link1; 

# Loop over the indexes of the array. 
# For very (very) large arrays it is 
# more efficient to use a C-style for loop: 
# for(my $i = 0; $i < @link; $i++) { 
foreach my $i (0..$#link) { 
    my $link = $link[$i]; 
    my $link1 = $link1[$i]; 

    print $fsas Get_Link_Text($link, $link1); 
} 

# Broke out your formatting code into a routine for readability. 
# Used a heredoc to make the formatting easier to read. 
# Also, took advantage of variable interpolation in the heredoc to further 
# improve readability. 
# I preserved the whitespace at the end of lines, is it really necessary? 
sub Get_Link_Text { 
    my $link = shift; 
    my $link1 = shift; 

    return <<"--END_TEXT--"; 
RUN PGM=HWYLOAD 
MATI=daily_trucks.MAT 
NETI=FAF_Network_V11.net 
NETO=MiamiDade.NET 
PARAMETERS MAXITERS=1, GAP=0.001, COMBINE=EQUI 
FUNCTION { 
TC[1] = T0*(1+0.15*(V/100)^(4))}  
FUNCTION V = (VOL[1]) 
PHASE=ILOOP 
PATHLOAD PATH=TIME, MW[1]=MI.1.1, SELECTLINK=(Link=$link), VOL[2]=MW[1] 
PATHLOAD PATH=TIME, MW[2]=MI.1.1, SELECTLINK=(Link=$link1), VOL[3]=MW[2] 
ENDPHASE 
ENDRUN 


--END_TEXT-- 
} 
+0

Gracias por las sugerencias y el código para hacerlo más legible y útil. – Krishnan

Cuestiones relacionadas