tags:

views:

348

answers:

4

I need to create a text file (aptest.s) that Ican use to read into another program. I am using Perl because I have a large list to work from. My code is as follows (which does not give the desired output - shown after code and actual output). Any help would be appreciated.

#!/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";
}
}

Actual 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=**319-116264||319-118664**), VOL[2]=MW[1] 
PATHLOAD SELECTLINK=(Link=**116380-320||116846-320**),      VOL[3]=MW[2] 
other output

Desired 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
A: 

Can you reduce the size of your code and example data while still reproducing the error? I can't immediately see the difference between the actual and expected output.

Sometimes, finding a minimal set of code and data that causes a problem will make the solution obvious.

Looking a bit more carefully, there's only one bit of output code that is 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";

Your bug is likely to be there.

Jon Ericson
Thanks to everyone for your comments and suggestions. I have made my code more readable and appreciate your input.
Krishnan
+13  A: 

See each_array in 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__
Sinan Ünür
Yes. That's probably what the questioner needs.
Jon Ericson
It was not easy to see because of all that noise in the script and the sample and desired output. To the OP, it is a good idea to reduce your problem to the smallest script still illustrating the issue.
Sinan Ünür
+4  A: 

I think you're trying to create four separate blocks, with each element from the link array associated with the corresponding element from the link2 array?

However you're actually outputting sixteen blocks, one for each combination of link and link1.

Instead try:

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

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

   ...
}
Alnitak
+2  A: 

Reading your question, it was difficult to tell what you really wanted to know. I believe Sinan Unur is correct, and that you want to iterate simultaneously over two arrays. As he says, List::MoreUtils provides the very handy each_array() function.

It is also simple to iterate over one or more arrays by index.

You can generate a list of indexes for use with a normal for loop. This uses $# to get the index of the last value in the array.

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

Or you can use a C-style for loop to generate your indexes. This uses the fact that an array evaluated in scalar context returns the number of elements.

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

It could also be written using $#:

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

Upon reading your code, it was clear that you aren't familiar with Perl's quoting operators. Using them effectively makes your scripts much easier to write and read.

In a friendly spirit, please allow me to tidy your script:

#!/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--
}
daotoad
Thanks for the suggestions and the code to make it more readable and useful.
Krishnan