tags:

views:

97

answers:

4
+3  Q: 

Transpose in perl

Hi all,

I have started learning perl and like to try out new things.

I have some problem in text processing. I have some text of the form,

0 1 2 3 4 5 6 7 8 9 10

6 7 3 6 9 3 1 5 2 4 6

I want to transpose this text. Like, I want to make rows as columns ans columns as rows. Id there a way to do this in perl?

Thank you all.

+2  A: 

There certainly is, and Mike has pointed out the simplest way. If you are learning, you probably want to write your own function?
First, you want to split each line on spaces to get an array of values (or push the list of words into the array, as in Dalton's answer; in Perl, there's always more than one way to do anything)
Then, for each element in the array, you want to print it and its counterpart in the second array onto the same line. (What will you do if one array runs out before the other?)

Of course, if you want to learn Perl, you will also definitely want to learn to use CPAN as well, so it's still worthwhile to try using Data::Pivot.

Larry Wang
Thank you for your suggestions. I would definitely try those.
jerrygo
+2  A: 

So this solution uses an array-of-arrays, each nested array is a row of data. Very simply you loop over the columns in each row and push them onto another array-of-arrays using the column index as the index which to push the value onto. This has the effect of pivoting the data as you requested.

#!/usr/bin/env perl

my @rows = ();
my @transposed = ();

# This is each row in your table
push(@rows, [qw(0 1 2 3 4 5 6 7 8 9 10)]);
push(@rows, [qw(6 7 3 6 9 3 1 5 2 4 6)]);

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";
}

This results in:

0 6 
1 7 
2 3 
3 6 
4 9 
5 3 
6 1 
7 5 
8 2 
9 4 
10 6
dalton
Thank you. Great solution :)
jerrygo
You do not need push for initialization: `@rows = ( [qw(0 1 2 3 4 5 6 7 8 9 10)], [qw(6 7 3 6 9 3 1 5 2 4 6)] );`
dolmen
That's true, you don't need to. But like everything else in perl there's more than one way to do it. :)
dalton
+2  A: 

Here's an outline of one way to transpose data. Working through this example will be instructive because you will need to use CPAN, you will learn about the useful List::Util and List::MoreUtils modules, you will learn the basics of complex data structures (see perlreftut, perldsc, and perllol), and you will get to use an iterator in Perl.

use strict;
use warnings;
use List::MoreUtils qw(each_arrayref);

my @raw_data = (
    '0 1 2 3 4 5 6 7 8 9 10',
    '6 7 3 6 9 3 1 5 2 4 6',
);

my @rows = ... ; # Look up map() and split() to fill in the rest.
                 # You want an array of arrays.

my @transposed;  # You will build this in the loop below.

my $iter = each_arrayref(@rows);  # See List::MoreUtils documentation.

while ( my @tuple = $iter->() ){
    # Do stuff here to build up @transposed, which
    # will also be an array of arrays.
}
FM
Thanks. Would try all those :)
jerrygo
A: 
use strict;
# read the first line
my @labels = split ' ', <>;
# read and ignore the empty second line
<>;
# read the third line
my @values = split ' ', <>;
# transpose (I suppose you'll do more with the table than just printing it)
my %table = map { $labels[$_] => $values[$_] } 0..$#labels;
# print
foreach (@labels) {
    print "$_ $table{$_}\n";
}
dolmen