如何在Perl中同时迭代多个列表?

如何在Perl中同时迭代多个列表?,perl,arrays,list,Perl,Arrays,List,我需要创建一个文本文件(aptest.s),我可以用它读入另一个程序。我使用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

我需要创建一个文本文件(aptest.s),我可以用它读入另一个程序。我使用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

您能否在仍然复制错误的同时减少代码和示例数据的大小?我无法立即看到实际输出和预期输出之间的差异

有时,找到一组导致问题的最小代码和数据将使解决方案变得显而易见

仔细观察,只有一位输出代码是可变的:

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

您的bug很可能存在。

请参见以下内容中的每个数组

我想您正在尝试创建四个独立的块,其中
链接
数组中的每个元素都与
链接2
数组中的相应元素相关联

然而,实际上您要输出16个块,每个块对应于
link
link1
的组合

相反,请尝试:

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

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

   ...
}

阅读你的问题,很难说出你真正想知道的。我相信Sinan Unur是正确的,并且您希望在两个数组上同时迭代。正如他所说,List::MoreUtils提供了非常方便的
each_array()
函数

按索引遍历一个或多个数组也很简单

您可以生成索引列表,以便与普通for循环一起使用。这将使用
$#
获取数组中最后一个值的索引

for ( 0..$#array ) { ... }
或者您可以使用C样式的for循环来生成索引。这使用了在标量上下文中计算的数组返回元素数这一事实

for ( my $i=0; $i<@array; $i++ ) { ... }
在阅读您的代码时,很明显您并不熟悉。有效地使用它们可以使脚本更易于编写和阅读

本着友好的精神,请允许我整理您的脚本:

#!/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--
}
#/usr/bin/perl
#始终:
严格使用;
使用警告;
#my$TARGET_DIR='D://projects//SW Model ODME';
我的$TARGET_DIR=';
我的$TARGET_文件='aptest.s';
#使用qw()可以生成一长串
#文字更易于键入和读取。
考虑到比链接和LIK1找到更好的名称。
#描述两者之间关系的东西
#这两个阵列。
我的@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
);
#检查chdir的结果。
chdir($TARGET_DIR)
或“无法输入$TARGET\u DIR-$!\n”;
#使用词法文件句柄。
#使用3 arg打开
#检查open的结果-您需要知道它是否失败。
打开(我的$fsas,“>>”,$TARGET_文件)
或“无法打开$TARGET\u文件-$!\n”;
#验证链路阵列的大小是否适当。
“die”链接数组的大小不同
除非@link==@link1;
#循环数组的索引。
#对于非常(非常)大的阵列,它是
#使用C样式for循环更有效:
#对于(我的$i=0;$i<@link;$i++){
foreach my$i(0..$#链接){
我的$link=$link[$i];
my$link1=$link1[$i];
打印$fsas Get_Link_Text($Link,$link1);
}
#为了便于阅读,将格式化代码分解成一个例程。
#使用heredoc使格式更易于阅读。
#此外,利用heredoc中的变量插值进一步
#提高可读性。
#我在行尾保留了空格,真的有必要吗?
子获取链接文本{
我的$link=shift;
我的$link1=班次;

回答是。这可能是提问者需要的。感谢大家的评论和建议。我已经使我的代码更具可读性,并感谢您的输入。感谢建议和代码,使其更具可读性和实用性。
for ( my $i=0; $i<=$#array; $i++ ) { ... }
#!/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--
}