Costumo usar python para processar diretórios de dados. Recentemente, percebi que a ordem padrão das listas mudou para algo quase sem sentido. Por exemplo, se estou em um diretório atual contendo os seguintes subdiretórios: run01, run02, ... run19, run20 e, a seguir, gero uma lista a partir do seguinte comando:
dir = os.listdir(os.getcwd())
então geralmente consigo uma lista nesta ordem:
dir = ['run01', 'run18', 'run14', 'run13', 'run12', 'run11', 'run08', ... ]
e assim por diante. A ordem costumava ser alfanumérica. Mas esta nova ordem permaneceu comigo por um tempo agora.
O que está determinando a ordem (exibida) dessas listas?
python
list
directory-listing
listdir
marshall.ward
fonte
fonte
listdir
saída classificada . Não sei por que as perguntas foram mescladas.Respostas:
Acho que a ordem tem a ver com a forma como os arquivos são indexados em seu FileSystem. Se você realmente deseja que ela siga alguma ordem, você pode sempre ordenar a lista depois de obter os arquivos.
fonte
Você pode usar a
sorted
função interna para classificar as strings como quiser. Com base no que você descreve,Como alternativa, você pode usar o
.sort
método de uma lista:Eu acho que deve fazer o truque.
Observe que a ordem que
os.listdir
obtém os nomes dos arquivos provavelmente depende completamente do seu sistema de arquivos.fonte
sorted(listdir)
funcionou para mim.listdir.sort()
me deu: TypeError: o objeto 'NoneType' não é iterávelreverse=True
para torná-lo tipo descendente.sorted
coisa escrita primeiro faz em uma única linha, OK?Pela documentação :
A ordem não é confiável e é um artefato do sistema de arquivos.
Para classificar o resultado, use
sorted(os.listdir(path))
.fonte
Python, por qualquer motivo, não vem com uma maneira embutida de ter classificação natural (ou seja, 1, 2, 10 em vez de 1, 10, 2), então você mesmo deve escrever:
Agora você pode usar esta função para classificar uma lista:
PROBLEMAS: Se você usar a função acima para classificar strings (por exemplo, nomes de pastas) e quiser classificá-las como o Windows Explorer faz, isso não funcionará corretamente em alguns casos extremos.
Esta função de classificação retornará resultados incorretos no Windows, se você tiver nomes de pastas com certos caracteres 'especiais'. Por exemplo, esta função irá classificar
1, !1, !a, a
, enquanto o Windows Explorer irá classificar!1, 1, !a, a
.Portanto, se você deseja classificar exatamente como o Windows Explorer faz no Python, você deve usar a função integrada do Windows StrCmpLogicalW via ctypes (isso é claro não funcionará no Unix):
Esta função é ligeiramente mais lenta do que
sorted_alphanumeric()
.Bônus:
winsort
também pode classificar caminhos completos no Windows .Alternativamente, especialmente se você usar Unix, você pode usar a
natsort
biblioteca (pip install natsort
) para classificar por caminhos completos de maneira correta (significando subpastas na posição correta).Você pode usá-lo assim para classificar caminhos completos:
Não o use para classificação normal apenas de nomes de pastas (ou strings em geral), pois é um pouco mais lento do que a
sorted_alphanumeric()
função acima.natsorted
biblioteca fornecerá resultados incorretos se você espera a classificação do Windows Explorer, então usewinsort()
para isso.fonte
print( sorted_aphanumeric(["1", "10", "2", "foo_10", "foo_8"]) )
->['1', '2', '10', 'foo_8', 'foo_10']
. Exatamente como esperado.natsorted
para implementar a funcionalidade de correspondência do Windows Explorer. Talvez você deva contribuir com uma solução? github.com/SethMMorton/natsort/issues/41Acho que por padrão a ordem é determinada com o valor ASCII. A solução para este problema é esta
fonte
Provavelmente é apenas a ordem que C
readdir()
retorna. Tente executar este programa C:A linha de construção deve ser semelhante
gcc -o foo foo.c
.PS Acabei de executar isso e seu código Python, e ambos me deram uma saída ordenada, então não posso reproduzir o que você está vendo.
fonte
Como no caso do meu requisito, tenho um caso como o
row_163.pkl
aquios.path.splitext('row_163.pkl')
,('row_163', '.pkl')
então preciso dividi-lo com base em '_' também.mas no caso de sua necessidade, você pode fazer algo como
Onde
e também para recuperação de diretório, você pode fazer
sorted(os.listdir(path))
e para o caso de gostar
'run01.txt'
ou'run01.csv'
você pode fazer assimfonte
Descobri que "classificar" nem sempre faz o que eu esperava. por exemplo, eu tenho um diretório como o abaixo, e o "sort" me dá um resultado muito estranho:
Parece que compara primeiro o primeiro personagem, se for o maior, seria o último.
fonte
('5' > '403') is True
.Da documentação :
Isso significa que a ordem provavelmente depende do sistema operacional / de arquivos, não tem uma ordem particularmente significativa e, portanto, não é garantido que seja algo em particular. Quantas respostas mencionadas: se preferir, a lista recuperada pode ser classificada.
Felicidades :)
fonte
A resposta de Elliot resolve perfeitamente, mas por se tratar de um comentário, passa despercebido então com o intuito de ajudar alguém, estou reiterando como solução.
Use a biblioteca natsort:
Instale a biblioteca com o seguinte comando para Ubuntu e outras versões do Debian
Python 2
Python 3
Os detalhes de como usar esta biblioteca podem ser encontrados aqui
fonte
sorted()
! Obrigadofonte
A combinação proposta de os.listdir e comandos classificados gera o mesmo resultado que o comando ls -l no Linux. O exemplo a seguir verifica essa suposição:
Portanto, para alguém que deseja reproduzir o resultado do conhecido comando ls -l em seu código Python, o ordenado (os.listdir (DIR)) funciona muito bem.
fonte