snape has asked for the wisdom of the Perl Monks concerning the following question:

Hi all, I came across a program which transpose the contents in the file. I would like to know what is meant by the line :  $outline[$i] = "\t" x $oldlastcol; The entire code is as follows:

while (<MYFILE>) { chomp; @line = split /\t/; $oldlastcol = $lastcol; $lastcol = $#line if $#line > $lastcol; for (my $i=$oldlastcol; $i < $lastcol; $i++) { $outline[$i] = "\t" x $oldlastcol; } for (my $i=0; $i <=$lastcol; $i++) { $outline[$i] .= "$line[$i]\t" } } for (my $i=0; $i <= $lastcol; $i++) { $outline[$i] =~ s/\s*$//g; print $outline[$i]."\n"; }
Thanks.

Replies are listed 'Best First'.
Re: Transpose the contents of the file
by johngg (Canon) on Jan 22, 2010 at 17:02 UTC

    The x as used here is the string multiplier, e.g.

    $ perl -E 'say q{abc} x 3;' abcabcabc $

    It can also be used as a list multiplier, e.g.

    $ perl -E ' > @arr = ( 0 ) x 5; > $arr[ 3 ] = 7; > say qq{Element $_: $arr[ $_ ]} for 0 .. $#arr;' Element 0: 0 Element 1: 0 Element 2: 0 Element 3: 7 Element 4: 0 $

    I hope this is helpful.

    Cheers,

    JohnGG

    Update: Expanded the second code example to make it clearer that an array has been initialised.

Re: Transpose the contents of the file
by AnomalousMonk (Archbishop) on Jan 22, 2010 at 17:26 UTC
      thanks
Re: Transpose the contents of the file
by Marshall (Canon) on Jan 24, 2010 at 02:33 UTC
    I think johngg has the "x" stuff nailed! I thought I'd show you a more Perl way to code this without 3 for(;;) loops, actually not any.

    The for(;;) type loops can be a big source of "off by one" errors. Perl is great because often this is not necessary! Below I passed around references to the 2-D array, but that didn't add much complication to the code.

    There are some limitations below, but I didn't see the need to go past the original code's capabilities. I think others have pointed out that there are modules like Text::Table, et al, but normally just adding enough space between columns in a print to cover 98 % case with one more space is enough (you don't want to run columns together so that they can't be parsed by another program, but one wacko line alignment per 20 pages won't throw the human reader off).

    Have fun Perling!

    #!/usr/bin/perl -w use strict; # transpose input. won't align right if rows don't have # same # num of things, but then again Op's version will go # pretty wacky with: 1 2 3 4 # a b c d e f my @inAoA; my @transposed_AoA; while (<DATA>) { chomp; #not needed for \s, but here for \t option push(@inAoA,[split(/\s/,$_)]); #could be \t too } transpose_2d_array(\@inAoA, \@transposed_AoA); dump_AoA (\@transposed_AoA); sub transpose_2d_array { my ($in_aref, $out_aref) = @_; foreach my $in_row (@$in_aref) { my $new_row =0; foreach my $col_ele (@$in_row) { push (@{$out_aref->[$new_row]},$col_ele); $new_row++; } } } sub dump_AoA #with tabs between columns { my $AoA_ref = shift; foreach my $aref (@$AoA_ref) { print join("\t",@$aref),"\n"; } } =PrintOut of above code: 1 a 2 b 3 c 4 d 5 e 6 f =cut __DATA__ 1 2 3 4 5 6 a b c d e f