我有一个165 x 165等级矩阵,每行的值为1-165。我想解析每一行并删除所有值> = 5,按递增顺序对每一行进行排序,然后将值1-5替换为原始矩阵中列的名称。
例如,对于行k,值1,2,3,4将在前两次转换后生成,并将替换为p,d,m,n,a。
答案 0 :(得分:1)
我假设你的数组包含一个数组数组......
Awk,Sed或Perl都没有多维数组。但是,可以使用数组数组在Perl中模拟它们。
$a[0]->[0] = xx;
$a[0]->[1] = yy;
[...]
$a[0]->[164] = zz;
$a[1]->[0] = qq;
$a[1]->[1] = rr;
[...]
$a[164]->[164] = vv;
这有意义吗?
我正在调用行$x
和列$y
,因此数组中的元素将为$array[$x]->[$y]
。这样好吗?
好的,您的列名将位于行$array[0]
中,因此如果我们在$array[$x]->[$y]
中找到小于5的值,则我们知道列名称位于$array[0]->[$y]
中。这样好吗?
for my $x (1..164) { #First row is column names
for my $y (0..164) {
if ($array[$x]->[$y] <= 5) {
$array[$x]->[$y] = $array[0]->[$y];
}
}
}
我只是遍历所有行,每行,所有列,并检查值。如果该值小于或等于5,我将其替换为列名。
我希望我不会为你做功课。
答案 1 :(得分:1)
这个GNU sed解决方案可能有用,虽然它需要扩展,因为我只使用10x10矩阵进行测试:
# { echo {a..j};for x in {1..10};do seq 1 10 | shuf |sed 'N;N;N;N;N;N;N;N;N;s/\n/ /g';done; }> test_data
# cat test_data
a b c d e f g h i j
4 5 9 3 6 2 10 8 7 1
3 7 4 2 1 6 10 5 8 9
10 9 3 1 2 7 8 5 6 4
5 10 4 9 7 8 1 3 6 2
8 6 5 9 1 4 3 2 7 10
2 8 9 3 5 6 10 1 4 7
3 9 8 2 1 4 10 6 7 5
3 7 2 1 8 6 10 4 5 9
1 10 8 3 6 5 4 2 7 9
7 2 3 5 6 1 10 4 8 9
# cat test_data |
sed -rn '1{h;d};s/[0-9]{2,}|[6-9]/0/g;G;s/\n|$/ &/g;s/$/&1 2 3 4 5 /;:a;s/^(\S*) (.*\n)(\S* )(.*)/\2\4\1\3/;ta;s/\n//;s/0[^ ]? //g;:b;s/([1-5])(.*)\1(.)/\3\2/;tb;p'
j f d a b
e d a c h
d e c j h
g j h c a
e h g f c
h a d i e
e d a f j
d c a h i
a h d g f
f b c h d
sed
命令的工作原理如下。
数据文件的第一行包含列标题存储在保留空间中,然后删除模式空间(当前行)。对于所有后续数据行,所有两个或更多数字数字以及值6到9将转换为0.附加列名称以及数据值的换行符。在换行符和字符串结尾之前插入空格。将数据转换为查找,并将排序的值(即1 2 3 4 5)添加到其中。删除换行符以及任何0值和关联的查找。值1到5将替换为查找中的列名。
编辑:
我可能误解了有关排序列或行的问题,如果是这样,这是一个最小的修复 - 用原始值替换1 2 3 4 5
并在使用查找中的列名替换数字数据之前执行数字排序。