Как я могу перебирать несколько списков одновременно в Perl? - PullRequest
9 голосов
/ 05 мая 2009

Мне нужно создать текстовый файл (aptest.s) , который Ican использовать для чтения в другую программу. Я использую 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";
}
}

Фактический объем производства :

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

Желаемый выход

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

Ответы [ 4 ]

21 голосов
/ 05 мая 2009

См. each_array в Список :: 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__
4 голосов
/ 05 мая 2009

I думаю вы пытаетесь создать четыре отдельных блока, с каждым элементом из массива link, связанным с соответствующим элементом из массива link2?

Однако на самом деле вы выводите шестнадцать блоков, по одному для каждой комбинации из link и link1.

Вместо этого попробуйте:

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

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

   ...
}
2 голосов
/ 05 мая 2009

Читая ваш вопрос, было трудно сказать, что вы действительно хотели узнать. Я считаю, что Sinan Unur верен, и вы хотите выполнять итерацию одновременно по двум массивам. По его словам, List :: MoreUtils предоставляет очень удобную функцию each_array().

Также легко выполнить итерацию по одному или нескольким массивам по индексу.

Вы можете создать список индексов для использования с нормальным циклом for. При этом используется $# для получения индекса последнего значения в массиве.

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

Или вы можете использовать цикл for в стиле C для генерации ваших индексов. При этом используется тот факт, что массив, вычисленный в скалярном контексте, возвращает количество элементов.

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

Он также может быть написан с использованием $#:

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

После прочтения вашего кода стало ясно, что вы не знакомы с операторами цитирования Perl . Эффективное их использование значительно упрощает написание и чтение ваших сценариев.

В дружеском духе, пожалуйста, позвольте мне привести в порядок ваш сценарий:

#!/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 голосов
/ 05 мая 2009

Можете ли вы уменьшить размер вашего кода и данных примера, продолжая воспроизводить ошибку? Я не могу сразу увидеть разницу между фактическим и ожидаемым результатом.

Иногда, поиск минимального набора кода и данных, вызывающих проблему, делает решение очевидным.

Если присмотреться, то только один бит выходного кода является переменным:

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

Ваша ошибка, вероятно, там.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...