akp
akp

Reputation: 13

Transposing an array of elements

I am trying to transpose an array.

I tried the following code...

#! /usr/bin/perl

use strict;
use warnings;
use autodie;

open my $fh, '<',"op.txt" || die "$!";
open my $wh , '>',"pwl.txt" || die "$!"; 
select ($wh);
while (my $line = <$fh>) { 
  my @rows = $line;
  my @transposed;
  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 $new_col, " ";
    }
    print "\n"; 
  }
}

**********INPUT FILE******

1 2 3
4 5 6
7 8 9

********** EXPECTED OUTPUT FILE *******

1 4 7
2 5 8
3 6 9

******** GENERATED OUTPUT FILE *******

Currently couldn't able print anything. script shows the error "can't use string ("1 4 7") as an array ref while "strict refs" in use

Reference: used the following reference... Transpose in perl however in this reference example, array input lines are declared manually where as i am trying to process a array which is in a text file

could anybody help me where i did mistake?

Many Thanks

Upvotes: 0

Views: 530

Answers (4)

Borodin
Borodin

Reputation: 126722

Here's a simpler way of doing this. It assumes all the rows are of the same length, and that all the lines in the file contain data -- i.e. there are no blank lines

The name of the input file is expected as a parameter on the command line, and the output is sent to STDOUT so it can be redirected on the command line. For instance

perl transpose.pl op.txt > pwl.txt


use strict;
use warnings 'all';

my @matrix = map [ split ], <>;

print "@$_\n" for @matrix;
print "\n";

my @transpose;

for my $i ( 0 .. $#{ $matrix[0] } ) {
    $transpose[$i] = [ map { $_->[$i] } @matrix ]
}

print "@$_\n" for @transpose;
print "\n";

output

1 2 3
4 5 6
7 8 9

1 4 7
2 5 8
3 6 9

Upvotes: 0

akp
akp

Reputation: 13

adding my @row =map [ split], $line to my initial code is helping to print the data to pwl.txt.

however its not printing side by side.. instead it is printing to new line. I guess because of this Mr.Borodin didn't include matrix in side while loop!


1
2
3

4
5
6

7
8
9

Upvotes: 0

Craig Estey
Craig Estey

Reputation: 33601

You did have to split input line as @dland suggested. But, there were a few other issues.

Here's the corrected code [please pardon the gratuitous style cleanup]:

#! /usr/bin/perl

use strict;
use warnings;
use autodie;

open my $fh, '<',"op.txt" || die "$!";
open my $wh , '>',"pwl.txt" || die "$!";

my @rows;
while (my $line = <$fh>) {
  my @line = split(" ",$line);
  push(@rows,\@line);
}
close($fh);

my @transposed;
for my $row (@rows) {
  push(@transposed,[]);
}

my $rowidx = -1;
for my $rowptr (@rows) {
  ++$rowidx;
  my $colidx = -1;
  for my $rowval (@$rowptr) {
    ++$colidx;
    ###printf("R=%d C=%d\n",$rowidx,$colidx);
    my $colptr = $transposed[$colidx];
    $colptr->[$rowidx] = $rowval;
  }
}

for my $new_row (@transposed) {
  for my $new_col (@$new_row) {
    print $wh $new_col, " ";
  }
  print $wh "\n";
}

close($wh);

Note: It's slightly harder to transpose a non-square matrix. The above code may need to be extended a bit for that.

Upvotes: 1

dland
dland

Reputation: 4419

You're trying to shove a scalar into an array:

my @row = $line;

I think what you really want is to split on spaces:

my @row = split / /, $line;

Upvotes: 0

Related Questions