Loop Logic Question

Discussion in 'Perl Misc' started by Chip, Dec 10, 2004.

  1. Chip

    Chip Guest

    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>
     
    Chip, Dec 10, 2004
    #1
    1. Advertising

  2. "Chip" <> wrote in message
    news:...

    > 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
     
    Richard Zilavec, Dec 10, 2004
    #2
    1. Advertising

  3. Chip

    Uri Guttman Guest

    >>>>> "RZ" == Richard Zilavec <> writes:

    >> 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.


    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

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
     
    Uri Guttman, Dec 10, 2004
    #3
  4. Chip wrote:
    >
    > 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
    --
    use Perl;
    program
    fulfillment
     
    John W. Krahn, Dec 11, 2004
    #4
  5. Chip

    Chip Guest

    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

    "John W. Krahn" <> wrote in message
    news:69Aud.51640$6f6.21451@edtnps89...
    >
    > 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
    > --
    > use Perl;
    > program
    > fulfillment
     
    Chip, Dec 11, 2004
    #5
  6. Chip

    Anno Siegel Guest

    John W. Krahn <> wrote in comp.lang.perl.misc:
    > Chip wrote:
    > >
    > > 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
     
    Anno Siegel, Dec 13, 2004
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    5
    Views:
    453
    Mumia W.
    Apr 20, 2007
  2. takayuki
    Replies:
    2
    Views:
    284
    Calvin Spealman
    Jun 16, 2008
  3. spike
    Replies:
    8
    Views:
    1,497
    Steve Holden
    Feb 9, 2010
  4. James Rasmussen

    Infinite Loop in Code -- Logic Error

    James Rasmussen, Jul 17, 2010, in forum: Ruby
    Replies:
    8
    Views:
    200
    James Rasmussen
    Jul 19, 2010
  5. Isaac Won
    Replies:
    9
    Views:
    397
    Ulrich Eckhardt
    Mar 4, 2013
Loading...

Share This Page