Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:
Greetings Monks,
I need to transpose a bi-dimentional array, so that rows become columns and vice-versa.
my @matrix = (
[ qw(ab cd ef gh)],
[ qw(ij kl mn op)],
[ qw(qr st uv wx)]
);
# should become
my @transposed = (
[ qw(ab ij qr)],
[ qw(cd kl st)],
[ qw(ef mn uv)],
[ qw(gh op wx)]
);
I found Math::Matrix, which has a "transpose" method. However, it only works with numerical matrices, and since my matrices are mostly text, I was wondering if there are any general purpose methods (or modules) to achieve this goal.
Thanks
20030721 Edit by Corion: Changed title from 'Transpose a bi-dimentional array'
Re: Transpose a bi-dimensional array
by dbwiz (Curate) on Jul 21, 2003 at 11:24 UTC
|
use mapcar;
my @matrix = (
[ qw(ab cd ef gh)],
[ qw(ij kl mn op)],
[ qw(qr st uv wx)]
);
my @transposed = mapcar {[@_]} @matrix;
print join( " ", @$_), $/ for @transposed;
__END__
ab ij qr
cd kl st
ef mn uv
gh op wx
Update
mapcar is now a function in tye's Algorithm::Loops.
The above example would becpme:
use Algorithm::Loops qw(MapCar);
my @matrix = (
[ qw(ab cd ef gh)],
[ qw(ij kl mn op)],
[ qw(qr st uv wx)]
);
my @transposed = MapCar {[@_]} @matrix;
print join( " ", @$_), $/ for @transposed;
With exactly the same result. | [reply] [d/l] [select] |
Re: Transpose a bi-dimensional array
by edan (Curate) on Jul 21, 2003 at 11:28 UTC
|
Or, you could just peek in the source of Math::Matrix, nick the transpose() method, un-OO-ify it, and ... voila!
#!perl -l
my @matrix = (
[ qw(ab cd ef gh)],
[ qw(ij kl mn op)],
[ qw(qr st uv wx)]
);
my $transposed = transpose(\@matrix);
local $" = ",";
print "@$_" for @$transposed;
sub transpose {
my $matrix = shift;
my @result;
my $m;
for my $col (@{$matrix->[0]}) {
push @result, [];
}
for my $row (@{$matrix}) {
$m=0;
for my $col (@{$row}) {
push(@{$result[$m++]}, $col);
}
}
return \@result;
}
Disclaimer: not my coding style! I just modified existing code to make a point (Use the Source, Luke)
-- 3dan | [reply] [d/l] |
Re: Transpose a bi-dimensional array
by Abigail-II (Bishop) on Jul 21, 2003 at 12:35 UTC
|
A totally different way than already presented using
tie:
package Tie::Transpose;
use strict;
use warnings;
sub TIEHASH {bless $_ [1] => $_ [0]}
sub FETCH {my ($y, $x) = split /$;/ => $_ [1]; $_ [0] [$x] [$y]}
sub STORE {die}
package main;
my $matrix = [[qw /ab cd ef/],
[qw /gh ij kl/],
[qw /mn op qr/],
[qw /st uv wx/]];
tie my %trans => 'Tie::Transpose', $matrix;
print $trans {0, 0}, "\n";
print $trans {0, 1}, "\n";
print $trans {0, 2}, "\n";
print $trans {0, 3}, "\n";
__END__
ab
gh
mn
st
You may want to work out some details before putting
this in production code.
Abigail
| [reply] [d/l] |
Re: Transpose a bi-dimensional array
by broquaint (Abbot) on Jul 21, 2003 at 11:31 UTC
|
With a liberal use of map then we get the following code
use Data::Dumper;
my @matrix = (
[ qw(ab cd ef gh)],
[ qw(ij kl mn op)],
[ qw(qr st uv wx)]
);
my @transposed = map {
my $i = $_;
[ map $matrix[$_]->[$i], 0 .. $#matrix ]
} 0 .. $#{$matrix[0]};
print Dumper(\@transposed);
__output__
$VAR1 = [
[
'ab',
'ij',
'qr'
],
[
'cd',
'kl',
'st'
],
[
'ef',
'mn',
'uv'
],
[
'gh',
'op',
'wx'
]
];
Not as elegant as dbwiz's solution, but effective nonetheless.
HTH
_________ broquaint | [reply] [d/l] |
Re: Transpose a bi-dimensional array
by jmcnamara (Monsignor) on Jul 21, 2003 at 11:29 UTC
|
#!/usr/bin/perl -wl
use strict;
use Data::Dumper;
my @matrix = (
[ qw(ab cd ef gh)],
[ qw(ij kl mn op)],
[ qw(qr st uv wx)]
);
my @transpose;
for my $aref (@matrix) {
my $i = 0;
push @{$transpose[$i++]}, $_ for @$aref;
}
print Dumper(@matrix);
print Dumper(@transpose);
__END__
--
John.
| [reply] [d/l] |
|
Hi John,
How to print the data to the specific file instead of in terminal?
Thanks
Anil
| [reply] |
|
| [reply] |
|
|