Loop Logic Question

C

Chip

Hi and thanks for reading this post.

I have a text file that I need to convert
from a vertical list to a horizontal comma
delimited file that will always have the
same number (12) items in it.

The first item in each line is a serial
number that is always 17 characters followed
by a model number, stock number, sale price,
cost, color, then a list of options which
can vary between 1 to 6.

I can split the vertical file on the "\n"
but will need a loop to add blank fields
to the end of the line if the options
do not total 6 so that the line always
has total of 12 fields even if there are
not a total of 6 options.

$filename = "vertical.txt";
open(FILE, "$filename") || die "Could not open $filename";
@array = <FILE>;
foreach $line (@array)
{
if ( $line =~ /[^\S{17}]/) #serial number
{
#code to make formatted file
}
}

Thanks for your time and any and all help
is appreciated.

Chip

Example files;

<vertical.txt>
2G1WF52E849457786
1WF19
9457786
24600.00
22988.78
White/Lt Gray/cloth
B34 FLOOR MATS
FE9 FEDERAL EMISSION EQUIPMENT
K34 ELECTRONIC SPEED CONTROL
2G1WF52EX49457241
1WF19
9457241
22725.00
21282.53
White/Light Gray Clth
B34 FLOOR MATS
FE9 FEDERAL EMISSION EQUIPMENT
K34 ELECTRONIC SPEED CONTROL
LA1 3.4 V6 ENGINE
MX0 4 SPEED AUTO W/OVERDRIVE
2G1WP551449281308
1WP19
9281308
32835.00
30542.19
Black/Lt Gray Leather
AW6 DRIVERS SIDE AIRBAG
CF5 ELECTRIC SUNROOF
FE9 FEDERAL EMISSION EQUIPMENT
L67 SUPERCHARGED 3.8L SFI V6
MX0 4 SPEED AUTO W/OVERDRIVE
UP0 AM/FM CASS/CD PLAYER
</vertical.txt>

<formatted file>
2G1WF52E849457786,1WF19,9457786,24600.00,22988.78,White/Lt Gray/cloth,B34
FLOOR MATS,FE9 FEDERAL EMISSION EQUIPMENT,K34 ELECTRONIC SPEED CONTROL,,,,
2G1WF52EX49457241,1WF19,9457241,22725.00,21282.53,White/Light Gray Clth,B34
FLOOR MATS,FE9 FEDERAL EMISSION EQUIPMENT,K34 ELECTRONIC SPEED CONTROL,LA1
3.4 V6 ENGINE,MX0 4 SPEED AUTO W/OVERDRIVE,,
2G1WP551449281308,1WP19,9281308,32835.00,30542.19,Black/Lt Gray Leather,AW6
DRIVERS SIDE AIRBAG,CF5 ELECTRIC SUNROOF,FE9 FEDERAL EMISSION EQUIPMENT,L67
SUPERCHARGED 3.8L SFI V6,MX0 4 SPEED AUTO W/OVERDRIVE,UP0 AM/FM CASS/CD
PLAYER,
</formatted file>
 
R

Richard Zilavec

I can split the vertical file on the "\n"
but will need a loop to add blank fields
to the end of the line if the options
do not total 6 so that the line always
has total of 12 fields even if there are
not a total of 6 options.

$filename = "vertical.txt";
open(FILE, "$filename") || die "Could not open $filename";
@array = <FILE>;
foreach $line (@array)
{
if ( $line =~ /[^\S{17}]/) #serial number
{
#code to make formatted file
}
}

Thanks for your time and any and all help
is appreciated.

Chip


Try using map with the join statement.

for(0 .. 11) {
$array[$_] = $_;
$array[$_] =~ s/^(.*)$/'$1'/;
}
$string = join(',', map { $array[$_] }(0 .. 11));

This produces which may be useful.

'0','1','2','3','4','5','6','7','8','9','10','11'


Richard Zilavec
 
U

Uri Guttman

RZ> Try using map with the join statement.

RZ> for(0 .. 11) {
RZ> $array[$_] = $_;

and how does that help pad the array to 12 elements?

RZ> $array[$_] =~ s/^(.*)$/'$1'/;

since you just assigned each element, you could have just assigned
"'$_'" instead.

RZ> }
RZ> $string = join(',', map { $array[$_] }(0 .. 11));

huh??? why the map/array thing? that is just the same as @array!!

RZ> This produces which may be useful.

RZ> '0','1','2','3','4','5','6','7','8','9','10','11'

doesn't look too useful to me. the OP wanted more than that.

and where is the critical logic that loops over the items and options
and converts each set to a single line?

what the OP needs is a double nested loop or similar to track when he
sees an item number. push the following lines into an array until the
next item number (and keep track of that). then pad the array with empty
elements using push( @array, () x (12 - @array) ) to get 12
elements. then do some postprocessing with map and join. i leave the
coding as an exercise.

uri
 
J

John W. Krahn

Chip said:
I have a text file that I need to convert
from a vertical list to a horizontal comma
delimited file that will always have the
same number (12) items in it.

The first item in each line is a serial
number that is always 17 characters followed
by a model number, stock number, sale price,
cost, color, then a list of options which
can vary between 1 to 6.

I can split the vertical file on the "\n"
but will need a loop to add blank fields
to the end of the line if the options
do not total 6 so that the line always
has total of 12 fields even if there are
not a total of 6 options.

$filename = "vertical.txt";
open(FILE, "$filename") || die "Could not open $filename";
@array = <FILE>;
foreach $line (@array)
{
if ( $line =~ /[^\S{17}]/) #serial number
{
#code to make formatted file
}
}

Example files;

<vertical.txt>
2G1WF52E849457786
1WF19
9457786
24600.00
22988.78
White/Lt Gray/cloth
B34 FLOOR MATS
FE9 FEDERAL EMISSION EQUIPMENT
K34 ELECTRONIC SPEED CONTROL
2G1WF52EX49457241
1WF19
9457241
22725.00
21282.53
White/Light Gray Clth
B34 FLOOR MATS
FE9 FEDERAL EMISSION EQUIPMENT
K34 ELECTRONIC SPEED CONTROL
LA1 3.4 V6 ENGINE
MX0 4 SPEED AUTO W/OVERDRIVE
2G1WP551449281308
1WP19
9281308
32835.00
30542.19
Black/Lt Gray Leather
AW6 DRIVERS SIDE AIRBAG
CF5 ELECTRIC SUNROOF
FE9 FEDERAL EMISSION EQUIPMENT
L67 SUPERCHARGED 3.8L SFI V6
MX0 4 SPEED AUTO W/OVERDRIVE
UP0 AM/FM CASS/CD PLAYER
</vertical.txt>

<formatted file>
2G1WF52E849457786,1WF19,9457786,24600.00,22988.78,White/Lt Gray/cloth,B34
FLOOR MATS,FE9 FEDERAL EMISSION EQUIPMENT,K34 ELECTRONIC SPEED CONTROL,,,,
2G1WF52EX49457241,1WF19,9457241,22725.00,21282.53,White/Light Gray Clth,B34
FLOOR MATS,FE9 FEDERAL EMISSION EQUIPMENT,K34 ELECTRONIC SPEED CONTROL,LA1
3.4 V6 ENGINE,MX0 4 SPEED AUTO W/OVERDRIVE,,
2G1WP551449281308,1WP19,9281308,32835.00,30542.19,Black/Lt Gray Leather,AW6
DRIVERS SIDE AIRBAG,CF5 ELECTRIC SUNROOF,FE9 FEDERAL EMISSION EQUIPMENT,L67
SUPERCHARGED 3.8L SFI V6,MX0 4 SPEED AUTO W/OVERDRIVE,UP0 AM/FM CASS/CD
PLAYER,
</formatted file>

This appears to do what you require:

#!/usr/bin/perl
use warnings;
use strict;

my $filename = 'vertical.txt';
open FILE, '<', $filename or die "Could not open $filename: $!";

my @data;
while ( <FILE> ) {
chomp;
if ( /^\w{17}$/ or eof FILE ) {
push @data, $_ if eof FILE;
if ( @data ) {
no warnings 'uninitialized';
print join( ',', @data[ 0 .. 12 ] ), "\n";
}
@data = $_;
}
else {
push @data, $_;
}
}

__END__



John
 
C

Chip

Thanks John,

That is exactly what I was looking for.

I like the "no warnings 'uninitialized';"
to join the array even if it does not
have data in it.

Thanks Again
Chip
 
A

Anno Siegel

John W. Krahn said:
Chip said:
I have a text file that I need to convert
from a vertical list to a horizontal comma
delimited file that will always have the
same number (12) items in it.

The first item in each line is a serial
number that is always 17 characters followed
by a model number, stock number, sale price,
cost, color, then a list of options which
can vary between 1 to 6.
[...]
Example files;

<vertical.txt>
2G1WF52E849457786
1WF19
9457786
24600.00
22988.78
White/Lt Gray/cloth
B34 FLOOR MATS
FE9 FEDERAL EMISSION EQUIPMENT
K34 ELECTRONIC SPEED CONTROL
2G1WF52EX49457241
1WF19
9457241
22725.00
21282.53
White/Light Gray Clth
B34 FLOOR MATS
FE9 FEDERAL EMISSION EQUIPMENT
K34 ELECTRONIC SPEED CONTROL
LA1 3.4 V6 ENGINE
MX0 4 SPEED AUTO W/OVERDRIVE
2G1WP551449281308
1WP19
9281308
32835.00
30542.19
Black/Lt Gray Leather
AW6 DRIVERS SIDE AIRBAG
CF5 ELECTRIC SUNROOF
FE9 FEDERAL EMISSION EQUIPMENT
L67 SUPERCHARGED 3.8L SFI V6
MX0 4 SPEED AUTO W/OVERDRIVE
UP0 AM/FM CASS/CD PLAYER
</vertical.txt>

<formatted file>
2G1WF52E849457786,1WF19,9457786,24600.00,22988.78,White/Lt Gray/cloth,B34
FLOOR MATS,FE9 FEDERAL EMISSION EQUIPMENT,K34 ELECTRONIC SPEED CONTROL,,,,
2G1WF52EX49457241,1WF19,9457241,22725.00,21282.53,White/Light Gray Clth,B34
FLOOR MATS,FE9 FEDERAL EMISSION EQUIPMENT,K34 ELECTRONIC SPEED CONTROL,LA1
3.4 V6 ENGINE,MX0 4 SPEED AUTO W/OVERDRIVE,,
2G1WP551449281308,1WP19,9281308,32835.00,30542.19,Black/Lt Gray Leather,AW6
DRIVERS SIDE AIRBAG,CF5 ELECTRIC SUNROOF,FE9 FEDERAL EMISSION EQUIPMENT,L67
SUPERCHARGED 3.8L SFI V6,MX0 4 SPEED AUTO W/OVERDRIVE,UP0 AM/FM CASS/CD
PLAYER,
</formatted file>

These output lines have 13 items each, not 12.
This appears to do what you require:

#!/usr/bin/perl
use warnings;
use strict;

my $filename = 'vertical.txt';
open FILE, '<', $filename or die "Could not open $filename: $!";

my @data;
while ( <FILE> ) {
chomp;
if ( /^\w{17}$/ or eof FILE ) {
push @data, $_ if eof FILE;
if ( @data ) {
no warnings 'uninitialized';
print join( ',', @data[ 0 .. 12 ] ), "\n";
}
@data = $_;
}
else {
push @data, $_;
}
}

__END__

That can be simplified a little. The only situation you need to
recognize in the loop is "is there a complete output record".
(I'm going for 12 items per record, not 13):

my @data;
while ( <DATA> ) {
chomp;
if ( ( /^\S{17}$/ or eof) and @data ) {
print join( ',', @data, ( '') x (12 - @data)), "\n";
@data = ();
}
push @data, $_;
}

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,021
Latest member
AkilahJaim

Latest Threads

Top