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