我已经开始学习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 :(得分:13)
因此,此解决方案使用每个嵌套数组的数组数组 是一行数据。很简单,你循环遍历每个列中的列 行并使用列将它们推送到另一个数组数组 index作为推动值的索引。这有效果 根据您的要求转动数据。
#!/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
答案 1 :(得分:5)
以下是一种转置数据的方法概述。通过这个示例将是有益的,因为您将需要使用CPAN,您将了解有用的List::Util
和List::MoreUtils
模块,您将学习复杂数据结构的基础知识(请参阅{ {3}},perlreftut和perldsc),您将在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.
}
答案 2 :(得分:3)
当然,迈克已经指出了最简单的方法。如果你正在学习,你可能想写自己的功能?
首先,您希望split空格中的每一行获取一组值(或push list of words到数组中,如Dalton's answer;在Perl中,总是不止一种方式做任何事情)
然后,for each element in the array,您要将它和第二个数组中的对应物打印到同一行。 (如果一个阵列在另一个阵列之前耗尽,你会怎么做?)
当然,如果你想学习Perl,你也肯定想学会使用CPAN,所以尝试使用Data :: Pivot仍然是值得的。
答案 3 :(得分:2)
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";
}
答案 4 :(得分: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'$n=@F-1if!$n;for(0..$n){push@{$$m[$_]},$F[$_]}'\
'END{print map{join"\t",@$_,"\n"}@$m}'
答案 5 :(得分:1)
use List::UtilsBy qw/zip_by/;
my @transposition = zip_by { [ @_ ] } @matrix;
答案 6 :(得分:1)
我在寻找一种方法来转置我通过读取文件构建的AoA时遇到了这个问题,但是,当然,此解决方案仍适用于任何AoA,并且不需要数组引用具有相同数量的元素。我知道这是一个古老的问题,但是在我仍在学习的过程中,如果有一些关于如何改善解决方案的批评/例子,那就太好了。
my $max_rows = 0;
foreach my $line (@copy) {
my $ref = ();
push @$ref, split(/\s+/, $line);
my $rows = scalar(@$ref);
$aoa[$i] = \@$ref;
$i++;
if ($rows > $max_rows) {
$max_rows = $rows;
}
}
for (my $i = 0; $i <= $max_rows; $i++) {
my @aoa_t = ();
for (my $k = 0; $k <= $#aoa; $k++) {
if ($aoa[$k]->[$i]) {
push @aoa_t, $aoa[$k]->[$i];
} else {
push @aoa_t, " ";
}
print " @aoa_t\n";
}
if ($aoa_t[0] eq " ") {
last;
} else {
$t_aoa[$i] = \@aoa_t;
}
}
它对于具有200多个以空格分隔的数据行的文件非常有效。如果在本论坛中合适的话,请提供任何反馈。问候。
答案 7 :(得分:0)
Array-Transpose-0.06怎么样?
答案 8 :(得分: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,这很重要