Подтвердить что ты не робот

Не буквенно-цифровой список из os.listdir()

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

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

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

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

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

sorted(os.listdir(whatever_directory))

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

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

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

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

Ответ 3

В документации :

os.listdir(путь)

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

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

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

Ответ 4

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

Вероятно, это просто порядок, возвращаемый 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.

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

Ответ 6

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

>>> 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']

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

Ответ 7

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.

Ответ 8

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]))

Ответ 9

Предлагаемая комбинация команд os.listdir и отсортированных генерирует тот же результат, что и команда ls -l под Linux. Следующий пример проверяет это предположение:

[email protected]:/tmp/test$ touch 3a 4a 5a b c d1 d2 d3 k l p0 p1 p3 q 410a 409a 408a 407a
[email protected]:/tmp/test$ ls -l
total 0
-rw-rw-r-- 1 user user 0 Feb  15 10:31 3a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 407a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 408a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 409a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 410a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 4a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 5a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 b
-rw-rw-r-- 1 user user 0 Feb  15 10:31 c
-rw-rw-r-- 1 user user 0 Feb  15 10:31 d1
-rw-rw-r-- 1 user user 0 Feb  15 10:31 d2
-rw-rw-r-- 1 user user 0 Feb  15 10:31 d3
-rw-rw-r-- 1 user user 0 Feb  15 10:31 k
-rw-rw-r-- 1 user user 0 Feb  15 10:31 l
-rw-rw-r-- 1 user user 0 Feb  15 10:31 p0
-rw-rw-r-- 1 user user 0 Feb  15 10:31 p1
-rw-rw-r-- 1 user user 0 Feb  15 10:31 p3
-rw-rw-r-- 1 user user 0 Feb  15 10:31 q

[email protected]:/tmp/test$ python
Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.listdir( './' )
['d3', 'k', 'p1', 'b', '410a', '5a', 'l', 'p0', '407a', '409a', '408a', 'd2', '4a', 'p3', '3a', 'q', 'c', 'd1']
>>> sorted( os.listdir( './' ) )
['3a', '407a', '408a', '409a', '410a', '4a', '5a', 'b', 'c', 'd1', 'd2', 'd3', 'k', 'l', 'p0', 'p1', 'p3', 'q']
>>> exit()
[email protected]:/tmp/test$ 

Итак, для тех, кто хочет воспроизвести результат известной команды ls -l в своем коде на Python, sorted (os.listdir(DIR)) работает очень хорошо.

Ответ 10

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

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

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

Python 2

sudo pip install natsort

Python 3

sudo pip3 install natsort

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

Ответ 11

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

dir = sorted(os.listdir(os.getcwd()), key=len)