2010-07-14 130 views
13

我已经开始学习perl并喜欢尝试新事物。在perl中转置

我在文本处理中遇到了一些问题。 我有形式的一些文字,

0 1 2 3 4 5 6 7 8 9 10 

6 7 3 6 9 3 1 5 2 4 6 

我要转此文本。就像,我想将行作为列和列作为行。有没有办法在Perl中做到这一点?

谢谢大家。

+0

感谢您的编辑。 :)让我知道如何将重要数据放在该块内。下次我会照顾它:) – jerrygo 2010-07-14 19:04:51

+0

每行缩进4个空格。 – 2010-07-14 19:08:31

+0

我想真正的Perl的方式是使用CPAN模块,如[Data :: Pivot](http://search.cpan.org/~bdulfer/Data-Pivot-0.05/Pivot.pm),但这可能不是你以后的挑战...... – Mike 2010-07-14 19:10:42

回答

12

所以这个解决方案使用了一个数组数组,每个嵌套数组 是一行数据。非常简单,您可以循环遍历每行 中的列,并使用索引 索引作为将值推入的索引将它们推送到另一个数组阵列。这可以根据您的要求转换数据的效果 。

#!/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"; 
} 

这导致:

0 6 
1 7 
2 3 
3 6 
4 9 
5 3 
6 1 
7 5 
8 2 
9 4 
10 6 
+0

谢谢。很好的解决方案:) – jerrygo 2010-07-14 19:51:37

+0

你不需要推动初始化:'@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 2010-07-15 14:08:18

+0

这是真的,你不需要。但是和perl中的其他一样,有不止一种方法可以做到这一点。 :) – dalton 2010-07-15 14:38:22

3

当然有,而且迈克指出了最简单的方法。如果你正在学习,你可能想写自己的功能?
首先,你要split在空间每行获得值的数组(或pushlist of words到阵列,如Dalton's answer;在Perl,总是有做任何事情的方法不止一种)
然后,for each element in the array,你想把它和第二个数组中的对象打印到同一行上。 (你会做什么,如果一个数组用完之前其他?)

当然,如果你想学习Perl的,你也一定要学会使用CPAN一样,所以它仍然是值得用数据来尝试::枢。

+0

谢谢你的建议。我一定会尝试这些。 – jerrygo 2010-07-14 19:49:53

5

这里的转置数据的一种方法的概述。通过这个例子的工作将是有益的,因为您将需要使用CPAN,您将了解到有用的List::UtilList::MoreUtils模块,您将学习复杂数据结构的基础知识(请参阅perlreftut,perldscperllol),您将得到在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. 
} 
+0

谢谢。将尝试所有这些:) – jerrygo 2010-07-14 19:49:34

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

这里是我的新的脚本来转制表符分隔的文件。如果您喜欢,请将\ t更改为您的分隔符。

#!/usr/bin/perl -anF/\t|\n/ 
$n = @F - 1 if !$n; 
for $i (0..$n) { 
    push @{ $m->[$i] }, $F[$i]; 
} 
END { 
    for $r (@$m) { 
     print join("\t", @$r), "\n"; 
    } 
} 

或作为104字符 “一个衬里”(与撇号反斜杠换行符撇号加入,以避免水平滚动):

perl -anF'\t|\n' -e'[email protected]!$n;for(0..$n){[email protected]{$$m[$_]},$F[$_]}'\ 
'END{print map{join"\t",@$_,"\n"}@$m}' 
0
use strict; 
my ($i, $rows, $cols) = (0, 10, 100); 
# initiate array 10x100 
my $array = [map {[map {$i++} (1..$cols)]} (1..$rows)]; 
# transpose array into 100x10 array 
my $transpose = [map {[map {shift @$_} @$array]} @{$array->[0]}]; 

阵列必须是一个矩阵,即列必须是相等的每一行,原始阵列将被破坏

这个代码将不使用额外的用于转置的内存,用于其他库的x2,用于大型阵列的例如100x1M,重要的是