Como classificar números em array pelo Unix?

7

Estou pensando se existe algum nome para uma função tão simples que retorne a ordem dos números em uma matriz. Eu realmente adoraria fazer essa classificação de maneira minimalista e com comandos básicos do Unix, mas não consigo pensar em nada além do find-and-loop básico, que não é tão elegante. Suponha que você tenha uma matriz de números

17 
94 
3 
52 
4 
4 
9

Saída esperada onde as duplicatas apenas recebem o mesmo ID; como lidar com duplicatas não é crítico, então sinta-se atento:

4 
6 
1 
5 
2 
2 
3        

Motivação: Hoje vi muitos usuários usando muitas maneiras diferentes para resolver esse problema e executar muitas etapas manuais com a Planilha. então comecei a pensar na maneira minimalista de fazer isso.

Comparando o algoritmo de classificação à classificação média do Google

Na Planilha do Google, use =arrayformula(rank.AVG(A:A,A:A,true)) e você é considerado uma referência como a ordem crescente, como a primeira saída esperada

17  5
94  7
3   1
52  6
4   2.5
4   2.5
9   4

onde você vê que meu algoritmo de classificação inicial é tendencioso. Eu acho que ser capaz de definir o local do conjunto de dados seria útil aqui.

    
por Léo Léopold Hertz 준영 19.09.2016 / 22:04

3 respostas

11

Se essa lista estivesse em file , um por linha, eu faria algo como:

sort -nu file |
  awk 'NR == FNR {rank[$0] = NR; next}
      {print rank[$0]}' - file

Se estivesse em um zsh $array :

sorted=(${(nou)array})
for i ($array) echo $sorted[(i)$i]

Esse é o mesmo princípio que para a versão awk acima, a classificação é o índice NR / (i) no numericamente ( -n / (n) ) ordenado ( sort / (o) ), uniqued ( -u / (u) ) lista de elementos.

Para sua classificação média:

sort -n file |
  awk 'NR == FNR {rank[$0] += NR; n[$0]++; next}
  {print rank[$0] / n[$0]}' - file

O que dá:

5
7
1
6
2.5
2.5
4

(use sort -rn para reverter a ordem, como na sua versão do Google Spreadsheet ).

    
por 19.09.2016 / 22:29
8
nl x | sort  -k 2n | nl | sort -k 2n | cut -f1

... tem um comportamento ligeiramente diferente no caso de duplicatas:

 nl x | sort  -k 2n | nl | sort -k 2n | cut -f1,3
 5  17 
 7  94 
 1  3 
 6  52 
 2  4 
 3  4 
 4  9
    
por 19.09.2016 / 23:18
6

Com apenas o GNU awk:

awk '
    FNR == NR {numbers[$1]=1; next} 
    FNR == 1 {
        n = asorti(numbers, sorted, "@ind_num_asc")
        for (i=1; i<=n; i++) rank[sorted[i]] = i
    }
    {print rank[$1]}
' file file
    
por 19.09.2016 / 22:45