Не алфавитно-цифровой порядок списка от os.listdir () - PullRequest
82 голосов
/ 27 января 2011

Я часто использую python для обработки каталогов данных.Недавно я заметил, что порядок списков по умолчанию изменился на что-то почти бессмысленное.Например, если я нахожусь в текущем каталоге, содержащем следующие подкаталоги: run01, run02, ... run19, run20, а затем я генерирую список из следующей команды:

dir = os.listdir(os.getcwd())

, тогда обычно получаюсписок в следующем порядке:

dir = ['run01', 'run18', 'run14', 'run13', 'run12', 'run11', 'run08', ... ]

и так далее.Порядок был буквенно-цифровой.Но этот новый порядок остался со мной некоторое время.

Что определяет (отображается) порядок этих списков?

Ответы [ 11 ]

97 голосов
/ 21 февраля 2013

Вы можете использовать встроенную функцию sorted для сортировки строк по своему усмотрению. Исходя из того, что вы описываете,

sorted(os.listdir(whatever_directory))

В качестве альтернативы, вы можете использовать .sort метод списка:

lst = os.listdir(whatever_directory)
lst.sort()

Я думаю, что должен сделать трюк.

Обратите внимание, что порядок, в котором os.listdir получает имена файлов, вероятно, полностью зависит от вашей файловой системы.

48 голосов
/ 27 января 2011

Я думаю, что порядок связан с тем, как файлы индексируются в вашей файловой системе. Если вы действительно хотите, чтобы он придерживался какого-то порядка, вы всегда можете отсортировать список после получения файлов.

38 голосов
/ 27 января 2011

Согласно документации :

os.listdir (путь)

Возврат списка содержащий имена записей в каталог, заданный путем. Список в произвольном порядке . Это не включить специальные записи "." а также «..», даже если они присутствуют в каталог.

На порядок нельзя положиться, и это артефакт файловой системы.

Чтобы отсортировать результат, используйте sorted(os.listdir(path)).

13 голосов
/ 30 декабря 2017

Python по какой-либо причине не имеет встроенного способа естественной сортировки (имеется в виду 1, 2, 10 вместо 1, 10, 2), поэтому вы должны написать его самостоятельно:

import re
def sorted_aphanumeric(data):
    convert = lambda text: int(text) if text.isdigit() else text.lower()
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] 
    return sorted(data, key=alphanum_key)

Теперь вы можете использовать эту функцию для сортировки списка:

dirlist = sorted_aphanumeric(os.listdir(...))
5 голосов
/ 27 января 2011

Вероятно, это просто порядок, который возвращает C readdir().Попробуйте запустить эту программу на C:

#include <dirent.h>
#include <stdio.h>
int main(void)
{   DIR *dirp;
    struct dirent* de;
    dirp = opendir(".");
    while(de = readdir(dirp)) // Yes, one '='.
        printf("%s\n", de->d_name);
    closedir(dirp);
    return 0;
}

Строка сборки должна выглядеть примерно так: gcc -o foo foo.c.

PS Просто запустили этот и ваш код Python, и они оба дали мне отсортированный выводЯ не могу воспроизвести то, что вы видите.

2 голосов
/ 29 января 2014

Я нашел "сортировка" не всегда делает то, что я ожидал.например, у меня есть каталог, как показано ниже, и «sort» дает мне очень странный результат:

>>> os.listdir(pathon)
['2', '3', '4', '5', '403', '404', '407', '408', '410', '411', '412', '413', '414', '415', '416', '472']
>>> sorted([ f for f in os.listdir(pathon)])
['2', '3', '4', '403', '404', '407', '408', '410', '411', '412', '413', '414', '415', '416', '472', '5']

Кажется, он сравнивает первый символ первым, если он самый большой, он будет последнимодин.

1 голос
/ 06 сентября 2017
aaa = ['row_163.pkl', 'row_394.pkl', 'row_679.pkl', 'row_202.pkl', 'row_1449.pkl', 'row_247.pkl', 'row_1353.pkl', 'row_749.pkl', 'row_1293.pkl', 'row_1304.pkl', 'row_78.pkl', 'row_532.pkl', 'row_9.pkl', 'row_1435.pkl']                                                                                                                                                                                                                                                                                                 
sorted(aaa, key=lambda x: int(os.path.splitext(x.split('_')[1])[0]))

Как и в случае моего требования, у меня есть случай, например row_163.pkl здесь os.path.splitext('row_163.pkl') разбит его на ('row_163', '.pkl'), поэтому нужно разделить его также на '_'.

, нов случае вашего требования вы можете сделать что-то вроде

sorted(aa, key = lambda x: (int(re.sub('\D','',x)),x))

где

aa = ['run01', 'run08', 'run11', 'run12', 'run13', 'run14', 'run18']

, а также для извлечения каталогов вы можете сделать sorted(os.listdir(path))

и для случаявроде 'run01.txt' или 'run01.csv' вы можете сделать так

sorted(files, key=lambda x : int(os.path.splitext(x)[0]))
1 голос
/ 21 февраля 2013
In [6]: os.listdir?

Type:       builtin_function_or_method
String Form:<built-in function listdir>
Docstring:
listdir(path) -> list_of_strings
Return a list containing the names of the entries in the directory.
path: path of directory to list
The list is in **arbitrary order**.  It does not include the special
entries '.' and '..' even if they are present in the directory.
0 голосов
/ 09 июля 2019

Я думаю, что по умолчанию порядок определяется значением ASCII. Решением этой проблемы является

dir = sorted(os.listdir(os.getcwd()), key=len)
0 голосов
/ 22 августа 2018

Ответ Эллиота решает его отлично, но, поскольку это комментарий, он остается незамеченным, поэтому, чтобы помочь кому-то, я повторяю это как решение.

ИспользованиеБиблиотека natsort:

Установите библиотеку с помощью следующей команды для Ubuntu и других версий Debian

Python 2

sudo pip install natsort

Python 3

sudo pip3 install natsort

Подробная информация о том, как использовать эту библиотеку здесь

...