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

Dear Monks, I am currently trying to transpose a file. The input file I have is input.txt . And I want to create a transposed file and name that input2.txt My input file looks like this
923.066 923.813 432.895 433.381 M1 M2
I want my input2.txt file to look like
923.066 432.895 M1 923.813 433.381 M2
This is the code I have written.
#!/usr/bin/perl use strict; use File::Path qw(rmtree); my @rows = (); my @transposed = (); open F1,"input.txt"; while(<F1>) { chomp; push @rows, [ split / / ]; } #print @rows; my $filein2 = "input2.txt"; unlink $filein2; open my $fileHandlein2, ">>", "input2.txt" or die "Can't open 'input2. +txt'\n"; for my $row (@rows) { for my $column (0 .. $#{$row}) { push(@{$transposed[$column]}, $row->[$column]); } } for my $new_row (@transposed) { for my $new_col (@{$new_row}) { print $fileHandlein2 $new_col, " "; } print "\n"; }

The output file generated looks like

500.000 1333.000 M1 600.000 1130.000 M3

Could you please let me know what mistake I am doing and how to modify my code so that I can get the transposed file?

thanks,

Replies are listed 'Best First'.
Re: Transpose a file
by VinsWorldcom (Prior) on May 09, 2016 at 12:21 UTC
Re: Transpose a file
by karlgoethebier (Abbot) on May 09, 2016 at 12:51 UTC
    Try this:
    use Text::CSV; use Array::Transpose; use Data::Dump; use feature qw (say); use strict; use warnings; my $file = q(data.txt); my $csv = Text::CSV->new ({ binary => 0, eol => $/,sep_char=>' ' }); my @data; open my $in, "<", $file or die $!; while (my $row = $csv->getline ($in)) { push @data, $row; } close $in; @data= transpose \@data; # dd \@data; open my $out, ">", "out.txt" or die $!; for (@data) {$csv->print ($out, $_)} close $out; __END__

    Update: VinsWorldcom mentioned it already... i couldn't type so fast ;-)...deleted unused variable

    Regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

Re: Transpose a file
by Corion (Patriarch) on May 09, 2016 at 11:10 UTC

    Why is $fileHandlein2 named that way? What purpose does it serve?

    When/where do you output the newline that should separate the rows in the transposed output?

    To what filehandle do you output the newline that should separate the rows in the transposed output?

Re: Transpose a file
by Discipulus (Canon) on May 09, 2016 at 11:13 UTC
    If I understand you are interested in something like Rotating an array

    update maybe you'll find this useful

    use strict; use warnings; my @aoa; my $row=0; while (<DATA>){ chomp; push @{$aoa[$row]}, split /\s+/; $row++; } foreach my $ar (@aoa){ for my $index (0..$#aoa){ print +(shift @{$aoa[$index]} || '--')," " ; } }continue{print "\n"} __DATA__ A1 A2 A3 B1 B2 B3 C1 C2 C3 d1 d2 d3 d4 #OUTPUT A1 B1 C1 d1 A2 B2 C2 d2 A3 B3 C3 d3 -- -- -- d4

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

      Hello Discipulus

      I found your method of creating the array of arrays

      push @{$aoa[$row]}, split /\s+/

      harder to follow than what the OP has. I tried them side by side and got the same results with both.

      use strict; use warnings; use Data::Dumper; my @aoa1; my @aoa2; my $row=0; while (<DATA>){ chomp; push @{$aoa1[$row]}, split /\s+/; $row++; push @aoa2, [ split /\s+/ ]; } print Dumper \@aoa1; print Dumper \@aoa2; __DATA__ A1 A2 A3 B1 B2 B3 C1 C2 C3
Re: Transpose a file
by NetWallah (Canon) on May 09, 2016 at 21:52 UTC
    One-liner:
    perl -na -E "BEGIN{$c=0}; $x[$_][$c]=$F[$_] for 0..$#F; $c++} {say qq|@$_| for @x" transpose-this.txt

            This is not an optical illusion, it just looks like one.

      OK and ++NetWallah but now you explain this to me: at first glance i saw the BEGIN and seemed to me not necessary, but after a while I saw $c++}  { part and i said: this is a typo.. but no! it compiles and run fine as all code you post.

      Removing the BEGIN block..

      perl -na -E "$x[$_][$c||0]=$F[$_] for 0..$#F; $c++} {say qq|@$_| for +@x"

      ..deparsed becomes:

      BEGIN { $^H{'feature_unicode'} = q(1); $^H{'feature_say'} = q(1); $^H{'feature_state'} = q(1); $^H{'feature_switch'} = q(1); } LINE: while (defined($_ = <ARGV>)) { our(@F) = split(' ', $_, 0); $x[$_][$c or 0] = $F[$_] foreach (0 .. $#F); ++$c; } { say "@$_" foreach (@x); }

      So your evil trick ;=) to use } { is to break the implicit loop created by -n ? and doing so you have a fictional END block?

      If so, I prefere (in this case) readabilty over magic:

      perl -na -E "$x[$_][$c||0]=$F[$_] for 0..$#F; $c++; END{say qq|@$_| for @x}"

      L*

      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
        > evil trick

        See "Eskimo greeting" in perlsecret.

        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
        Thanks for the de-parse (++). I will agree with you on the readability of the END block vs Eskimo greeting.

        In the same spirit, I think the $c=0 initialization in the BEGIN block is clearer than [$c||0].

                This is not an optical illusion, it just looks like one.