classificando lexicograficamente por “todos os campos”

4

Aqui está um exemplo muito simples (embora artificial) para ilustrar o problema. Suponha que eu tenha um arquivo /tmp/table , com o seguinte conteúdo:

px9xc
px12xc
pqx12xc
pqx9xc

Aqui, o caractere x deve ser um separador de campos . Assim, o arquivo contém uma tabela de 4 linhas e 3 colunas. (Daqui em diante, vou me referir às colunas como "campos".)

Eu quero classificar esta tabela lexicograficamente em relação aos campos. Com isso quero dizer que se duas linhas tiverem valores idênticos no campo 1, então o empate será quebrado pela classificação de acordo com o campo 2, e se os valores no campo 2 também forem idênticos, então classifique de acordo com o campo 3. 1 NB: dentro de cada campo, assumimos a ordem padrão de sort .

Isso significa que, para a tabela em /tmp/table , a ordem desejada é

px12xc
px9xc
pqx12xc
pqx9xc

(Observe que, na ordem padrão de sort , 12 vem antes de 9 .)

Uma simples invocação de sort não produzirá a ordem desejada, porque os separadores de campo não serão interpretados como tal:

% sort /tmp/table
pqx12xc
pqx9xc
px12xc
px9xc

Isso também não produz a ordem desejada:

% sort -tx -k1,3 /tmp/table
pqx12xc
pqx9xc
px12xc
px9xc

A única maneira que encontrei para obter a ordem desejada usando sort (pelo menos a que está instalada no meu sistema, a saber, GNU's) é esta:

% sort -tx -k1,1 -k2,2 -k3,3 /tmp/table
px12xc
px9xc
pqx12xc
pqx9xc

O problema com essa solução (além do tédio de especificar tantas opções -k?,? quanto os campos) é que ela não é generalizada para tabelas com um número diferente de campos.

Existe uma maneira conveniente (seja com sort ou de outra forma) para aplicar o ordenamento lexicográfico baseado em campo a "todos os campos"?

1 Em geral, se a tabela tiver campos N , para decidir qual das duas linhas vem primeiro na ordem lexicográfica, aplica-se a seguinte regra recursiva , deixando que k varie de 1 a N : se as duas linhas forem idênticas em seus valores para os campos 1 a k - 1, então quebre o empate de acordo com o valor no campo k -th.

    
por kjo 01.09.2016 / 20:44

1 resposta

5

Podemos trapacear e substituir o caractere separador por outro (por exemplo, o caractere NUL) que permitiria a classificação "nativa" funcionar e, em seguida, defini-lo novamente.

por exemplo

tr x '
tr x '
ab  | def
abc | def
0' < file.txt | LANG=C sort | tr '
abc | def
abc | ghi
0' x
0' < file.txt | sort | tr '
tr x '
tr x '
ab  | def
abc | def
0' < file.txt | LANG=C sort | tr '
abc | def
abc | ghi
0' x
0' < file.txt | sort | tr '%pre%0' x
0' x

Agora, talvez seja necessário ter cuidado com o impacto local na encomenda, por isso talvez seja necessário fazer

%pre%

Isso só funciona enquanto os dados não tiverem NULs!

Como isso funciona pode ser explicado mais facilmente com uma tabela formatada:

Precisamos comparar duas linhas:

%pre%

Definimos o separador como NUL e comparamos ab<NUL>def a abc<NUL>def . O <NUL> vem antes de c e, portanto, classificamos corretamente no primeiro campo.

Agora vamos dizer que o primeiro campo corresponde e o segundo campo é diferente

%pre%

Agora, comparamos abc<NUL>def a abc<NUL>ghi . Temos uma correspondência entre o primeiro campo e o separador e agora estamos classificando no segundo campo.

    
por 01.09.2016 / 21:14

Tags