Làm thế nào để sắp xếp theo chiều dọc và chiều ngang?


7

Trước (INPUT.txt):

    Foo#1   Foo#2   Foo#3   Foo#4   Foo#4   Foo#5   SUM
Bar#1   0   0   0   0   3   0   3
Bar#2   2   0   1   0   0   0   3
Bar#3   0   0   0   2   2   0   4
Bar#4   0   0   1   1   2   0   4
Bar#5   1   0   1   0   0   0   2
Bar#6   3   20  0   0   1   0   24
Bar#7   1   0   2   0   0   0   3
SUM 7   20  5   3   8   0   43

Sau (OUTPUT.txt):

    Foo#2   Foo#4   Foo#1   Foo#3   Foo#4   Foo#5   SUM
Bar#6   20  1   3   0   0   0   24
Bar#3   0   2   0   0   2   0   4
Bar#4   0   2   0   1   1   0   4
Bar#1   0   3   0   0   0   0   3
Bar#2   0   0   2   1   0   0   3
Bar#7   0   0   1   2   0   0   3
Bar#5   0   0   1   1   0   0   2
SUM 20  8   7   5   3   0   43

Câu hỏi khó: Làm thế nào để sắp xếp theo chiều dọc và chiều ngang theo cột SUM và hàng trong bash hoặc perl?

Ảnh chụp màn hình:

Trước:

nhập mô tả hình ảnh ở đây

Sau:

nhập mô tả hình ảnh ở đây

Câu trả lời:


3

Điều đó tương đối dễ dàng với perl:

perl -F'\s+' -lane '
  push @row, [@F];
  END{
    @sum = @{pop @row};
    @col = (0, (sort {$sum[$b] <=> $sum[$a]} (1..$#sum-1)), $#sum);
    for $i ($row[0], (sort {$b->[$#sum] <=> $a->[$#sum]} @row[1..$#row]), \@sum) {
      print join "\t", @{$i}[@col]
    }
  }'

Tôi nghĩ bạn không bình thường. Bạn có phải là người ngoài hành tinh? : D Cảm ơn: D
somelooser28533

Tương đối dễ dàng? Liên quan đến cái gì?
dotancohen

Dễ dàng hơn viết nó trong trình biên dịch :)
Barmar

6

Vấn đề là hai lần, đầu tiên bạn muốn sắp xếp các #barhàng theo giá trị số của cột H, đây là một hoạt động sắp xếp khá tầm thường trong hầu hết các công cụ dòng lệnh định hướng dòng,sort -nr -k8,1 input.txt |column -t > intermediate1.txt

Tiêu đề của bảng và hàng tổng của bạn yêu cầu một số xáo trộn thủ công, nhưng sau đó kết quả trung gian là:

-      Foo#1  Foo#2  Foo#3  Foo#4  Foo#4  Foo#5  SUM
Bar#6  3      20     0      0      1      0      24
Bar#4  0      0      1      1      2      0      4
Bar#3  0      0      0      2      2      0      4
Bar#7  1      0      2      0      0      0      3
Bar#2  2      0      1      0      0      0      3
Bar#1  0      0      0      0      3      0      3
Bar#5  1      0      1      0      0      0      2
SUM    7      20     5      3      8      0      43

Thứ hai là phức tạp hơn một chút, xáo trộn các cột dựa trên các giá trị tổng cột trong hàng dưới cùng.

Vấn đề trở nên dễ dàng hơn rất nhiều để giải quyết khi bạn lần đầu tiên chuyển đổi ma trận của mình, tức là chuyển các cột thành hàng và ngược lại, khi đó hoạt động của bạn lại là một cách sắp xếp cột đơn giản. Sử dụng mã GNU awk này từ stack stack:

awk '
{
    for (i=1; i<=NF; i++)  {
        a[NR,i] = $i
    }
}
NF>p { p = NF }
END {
    for(j=1; j<=p; j++) {
        str=a[1,j]
        for(i=2; i<=NR; i++){
            str=str" "a[i,j];
        }
        print str
    }
}' intermediate1.txt | column -t > intermediate2.txt

nhận được kết quả trung gian tiếp theo:

-      Bar#6  Bar#4  Bar#3  Bar#7  Bar#2  Bar#1  Bar#5  SUM
Foo#1  3      0      0      1      2      0      1      7
Foo#2  20     0      0      0      0      0      0      20
Foo#3  0      1      0      2      1      0      1      5
Foo#4  0      1      2      0      0      0      0      3
Foo#4  1      2      2      0      0      3      0      8
Foo#5  0      0      0      0      0      0      0      0
SUM    24     4      4      3      3      3      2      43

Bây giờ ma trận này có thể được sắp xếp theo giá trị của cột tổng sort -k9,1 -nr intermediate2.txt > intermediate3.txt, sau khi sửa thủ công thứ tự của tiêu đề và dòng tổng sẽ như sau:

-      Bar#6  Bar#4  Bar#3  Bar#7  Bar#2  Bar#1  Bar#5  SUM
Foo#2  20     0      0      0      0      0      0      20
Foo#4  1      2      2      0      0      3      0      8
Foo#1  3      0      0      1      2      0      1      7
Foo#3  0      1      0      2      1      0      1      5
Foo#4  0      1      2      0      0      0      0      3
Foo#5  0      0      0      0      0      0      0      0
SUM    24     4      4      3      3      3      2      43

Sau đó, sử dụng mã awk giống như trước đây, hoán chuyển kết quả trung gian ở trên trở lại để trở về bố cục ban đầu của các cột và hàng:

awk '
{
    for (i=1; i<=NF; i++)  {
        a[NR,i] = $i
    }
}
NF>p { p = NF }
END {
    for(j=1; j<=p; j++) {
        str=a[1,j]
        for(i=2; i<=NR; i++){
            str=str" "a[i,j];
        }
        print str
    }
}' intermediate3.txt | column -t > output.txt

và kết quả được định dạng độc đáo:

-      Foo#2  Foo#4  Foo#1  Foo#3  Foo#4  Foo#5  SUM
Bar#6  20     1      3      0      0      0      24
Bar#4  0      2      0      1      1      0      4
Bar#3  0      2      0      0      2      0      4
Bar#7  0      0      1      2      0      0      3
Bar#2  0      0      2      1      0      0      3
Bar#1  0      3      0      0      0      0      3
Bar#5  0      0      1      1      0      0      2
SUM    20     8      7      5      3      0      43

Thứ tự của Thanh số 4 và Thanh số 3 bị đảo ngược so với kết quả ví dụ vì giá trị tổng là giống hệt nhau, nhưng thứ tự sắp xếp giảm dần cũng được theo sau trong cột A, tương tự cho Thanh số 7, Thanh số 2 và Thanh số 1


Cảm ơn nhiều! Một perl ngắn hơn, wow: \
somelooser28533

2

Đối với hồ sơ, một pythongiải pháp.

from pprint import pprint
x = [(0,0,0,0,3,0),
(2,0,1,0,0,0),
(0,0,0,2,2,0),
(0,0,1,1,2,0),
(1,0,1,0,0,0),
(3,20,0,0,1,0),
(1,0,2,0,0,0)
]
y = sorted(x, key=sum, reverse=True)
pprint(zip(*sorted(zip(*y), key=sum, reverse=True)))
[(20, 1, 3, 0, 0, 0),
 (0, 2, 0, 0, 2, 0),
 (0, 2, 0, 1, 1, 0),
 (0, 3, 0, 0, 0, 0),
 (0, 0, 2, 1, 0, 0),
 (0, 0, 1, 2, 0, 0),
 (0, 0, 1, 1, 0, 0)]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.