Como executar uma ordenação personalizada

0

Eu tenho a seguinte linha em um arquivo:

[[0, [0, '1']], [1, [0, '2']], [2, [0, '3']], [3, [0, '4']]]
[[0, [1, '5']], [1, [1, '6']], [2, [1, '7']], [3, [1, '8']]]
[[0, [2, '9']], [1, [2, '10']], [2, [2, '11']], [3, [2, '12']]]

Existe uma maneira de classificá-los no primeiro caractere (0,1,2 ou 3) no elemento da lista interna para que eu termine com o seguinte:

[[0, [0, '1']], [0, [1, '5']],[0, [2, '9']]]
[[1, [0, '2']], [1, [1, '6']],[1, [2, '10']]] 

e assim por diante?

    
por Andrez 03.12.2013 / 17:10

1 resposta

2

Bem, isso não é particularmente elegante, mas fará o que você precisa. Pelo menos, no exemplo que você postou:

perl -ne 'while(s/(\[(\d),\s*\[.+?\]\])//){push @{$k{$2}},$1 . ",";} 
          END{ print "[@{$k{$_}}]\n" for keys(%k)}' file.txt | 
sed 's/,\]$/\]/' | sort

A execução do comando acima em um arquivo chamado file.txt que contém as linhas do seu exemplo fornece a seguinte saída:

[[0, [0, '1']], [0, [1, '5']], [0, [2, '9']]]
[[1, [0, '2']], [1, [1, '6']], [1, [2, '10']]]
[[2, [0, '3']], [2, [1, '7']], [2, [2, '11']]]
[[3, [0, '4']], [3, [1, '8']], [3, [2, '12']]]

Explicação

Eu não vou explicar em detalhes, já que este é realmente um pequeno programa e usa alguns recursos do Perl. A ideia básica do script Perl é encontrar todos os casos de [\d, [.+?]] , em que \d é qualquer número e .+?]] é tudo para o primeiro ]] . Isso basicamente irá coletar todos os diferentes sub-arrays ou tuplas, ou seja o que for, e salvá-los em um hash de arrays cuja chave é o primeiro dígito, aquele em que você deseja classificar. Uma vez que o arquivo inteiro tenha sido processado, ele imprimirá cada array do hash. Esta é a saída do script sozinho:

$ perl -ne 'while(s/(\[(\d),\s*\[.+?\]\])//){push @{$k{$2}},$1 . ",";} 
          END{ print "[@{$k{$_}}]\n" for keys(%k)}' file.txt 
[[1, [0, '2']], [1, [1, '6']], [1, [2, '10']],]
[[3, [0, '4']], [3, [1, '8']], [3, [2, '12']],]
[[0, [0, '1']], [0, [1, '5']], [0, [2, '9']],]
[[2, [0, '3']], [2, [1, '7']], [2, [2, '11']],]

Eu estou separando cada sub-array com , , mas isso significa que eu recebo um extra no final, então eu uso sed para remover isso.

$ perl -ne 'while(s/(\[(\d),\s*\[.+?\]\])//){push @{$k{$2}},$1 . ",";} 
>           END{ print "[@{$k{$_}}]\n" for keys(%k)}' file.txt | 
> sed 's/,\]$/\]/' 
[[1, [0, '2']], [1, [1, '6']], [1, [2, '10']]]
[[3, [0, '4']], [3, [1, '8']], [3, [2, '12']]]
[[0, [0, '1']], [0, [1, '5']], [0, [2, '9']]]
[[2, [0, '3']], [2, [1, '7']], [2, [2, '11']]]

Finalmente, você também queria isso classificado, mas como agora eles estão organizados pelo primeiro caractere, um sort simples será o seguinte:

$ perl -ne 'while(s/(\[(\d),\s*\[.+?\]\])//){push @{$k{$2}},$1 . ",";} 
          END{ print "[@{$k{$_}}]\n" for keys(%k)}' file.txt | 
sed 's/,\]$/\]/' | sort
[[0, [0, '1']], [0, [1, '5']], [0, [2, '9']]]
[[1, [0, '2']], [1, [1, '6']], [1, [2, '10']]]
[[2, [0, '3']], [2, [1, '7']], [2, [2, '11']]]
[[3, [0, '4']], [3, [1, '8']], [3, [2, '12']]]
    
por 03.12.2013 / 17:54

Tags