【问题标题】:Sort values and output the indices of their sorted columns对值进行排序并输出其排序列的索引
【发布时间】:2014-03-30 02:06:28
【问题描述】:

我有一个看起来像这样的文件:

20 30 40
80 70 60
50 30 40

每一列代表一个过程。我想知道每一行的程序是如何进行的。我的理想输出是

3 2 1
1 2 3
1 3 2

即在第 1 行中,第三列的值最高,其次是第二列,然后是第一列的最小值(这可以颠倒,没关系)。

我该怎么做?

【问题讨论】:

    标签: sorting unix awk cut


    【解决方案1】:

    我会使用其他一些 Unix 工具(当然是readcatsortcuttrsedbash):

    while read line
    do
      cat -n <(echo "$line" | sed 's/ /\n/g') | sort -r -k +2 | cut -f1 | tr '\n' ' '
      echo
    done < input.txt
    

    输出如下:

     3      2      1 
     1      2      3 
     1      3      2 
    

    【讨论】:

    • 这里面有没有只需要三栏文件的部分?因为我的实际文件远不止三列。
    • 不,该解决方案是通用的,适用于任意数量的列。
    • 哦,不,我很抱歉。这是正确的。我在考虑每一列是该行的该列值的排名,但当然这不是我在问题中提出的问题,抱歉。
    • 无需更改,原样完美,非常感谢!
    • 对于其他版本,您可以使用while read line; do for i in $line; do cat -n &lt;(echo "$line" | sed 's/ /\n/g' | sort -r -k +2) | grep "$i$" | { read a b; echo "$a"; }; done | tr '\n' ' '; echo; done
    【解决方案2】:

    使用 Python 的另一种解决方案:

    $ python
    Python 2.7.6 (default, Jan 26 2014, 17:25:18)
    [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>>
    >>> with open('file.txt') as f:
    ...    lis=[x.split() for x in f]
    ...
    >>> for each in lis:
    ...     each = [i[0] + 1 for i in sorted(enumerate(each), key=lambda x:x[1], reverse=True)]
    ...     print ' '.join([str(item) for item in each])
    ...
    3 2 1
    1 2 3
    1 3 2
    

    【讨论】:

      【解决方案3】:

      使用 Gnu awk 版本 4:

      $ awk 'BEGIN{ PROCINFO["sorted_in"]="@val_num_desc" }
      {
          split($0,a," ")
          for (i in a) printf "%s%s", i,OFS
          print ""
      }' file
      
      3 2 1 
      1 2 3 
      1 3 2 
      

      【讨论】:

        【解决方案4】:

        如果您有GNU awk,那么您可以执行以下操作:

        awk '{
            y = a = x = j = i = 0;
            delete tmp;
            delete num;
            delete ind;
            for(i = 1; i <= NF; i++) {
                num[$i, i] = i
            }
            x = asorti(num)
            for(y = 1; y <= x; y++) {
                split(num[y], tmp, SUBSEP)
                ind[++j] = tmp[2]
        }
        for(a = x; a >= 1; a--) {
            printf "%s%s", ind[a],(a==1?"\n":" ")
        }
        }' file
        

        $ cat file
        20 30 40
        0.923913 0.913043 0.880435 0.858696 0.826087 0.902174 0.836957 0.880435
        80 70 60
        50 30 40
        

        awk '{
            y = a = x = j = i = 0;
            delete tmp;
            delete num;
            delete ind;
            for(i = 1; i <= NF; i++) {
                num[$i, i] = i
            }
            x = asorti(num)
            for(y = 1; y <= x; y++) {
                split(num[y], tmp, SUBSEP)
                ind[++j] = tmp[2]
        }
        for(a = x; a >= 1; a--) {
            printf "%s%s", ind[a],(a==1?"\n":" ")
        }
        }' file
        3 2 1
        1 2 6 8 3 4 7 5
        1 2 3
        1 3 2
        

        【讨论】:

        • 我试过这个,第一行是 0.923913 0.913043 0.880435 0.858696 0.826087 0.902174 0.836957 0.880435,得到了 1 2 6 8 4 7 5。Alfe 的脚本也试图做错了 16822这个脚本给出了相同的顺序,但是 3 已经消失了。
        • 啊,有重复的数字。 0.880435 出现两次,因此密钥被覆盖。让我试着修复它。
        • @AndrewLatham 更新了解决方案。
        【解决方案5】:

        通过 perl 解决

        #!/usr/bin/perl
        open(FH,'<','/home/chidori/input.txt') or die "Can't open file$!\n";
        while(my $line=<FH>){
                chomp($line);
                my @unsorted_array=split(/\s/,$line);
                my $count=scalar @unsorted_array;
                my @sorted_array = sort { $a <=> $b } @unsorted_array;
                my %hash=map{$_ => $count--} @sorted_array;
        
                foreach my $value(@unsorted_array){
                        print "$hash{$value} ";
                }
        
                print "\n";
        }
        

        【讨论】:

          猜你喜欢
          • 2012-03-09
          • 2018-08-19
          • 1970-01-01
          • 1970-01-01
          • 2021-05-17
          • 1970-01-01
          • 2016-01-01
          • 1970-01-01
          • 2010-11-18
          相关资源
          最近更新 更多