Python 3.x сортирует имена файлов, которые содержат цифры и буквы в списке - PullRequest
0 голосов
/ 12 июня 2018

У меня есть следующий код Python для сортировки списка имен файлов

list_of_dwg = [
    r'\\pc_name\AHL-4604-0002-10.dwg',
    r'\\pc_name\AHL-4604-0002-11A.dwg',
    r'\\pc_name\AHL-4604-0002-4.dwg',
    r'\\pc_name\AHL-4604-0002-1_FRONT COVER.dwg',
    r'\\pc_name\AHL-4604-0002-2_MASTER LIST.dwg',
    r'\\pc_name\AHL-4604-0002-3_LEGEND LIST.dwg',

]

list_of_dwg_sorted = sorted(list_of_dwg)

for dwg in list_of_dwg_sorted:
    print(dwg)

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

\\pc_name\AHL-4604-0002-10.dwg
\\pc_name\AHL-4604-0002-11A.dwg
\\pc_name\AHL-4604-0002-1_FRONT COVER.dwg
\\pc_name\AHL-4604-0002-2_MASTER LIST.dwg
\\pc_name\AHL-4604-0002-3_LEGEND LIST.dwg
\\pc_name\AHL-4604-0002-4.dwg

Но это мой идеалвывод на основе отображения проводника Windows

\\pc_name\AHL-4604-0002-1_FRONT COVER.dwg
\\pc_name\AHL-4604-0002-2_MASTER LIST.dwg
\\pc_name\AHL-4604-0002-3_LEGEND LIST.dwg
\\pc_name\AHL-4604-0002-4.dwg
\\pc_name\AHL-4604-0002-10.dwg
\\pc_name\AHL-4604-0002-11A.dwg

Любая идея будет отличным подспорьем.Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 12 июня 2018

Вот ключевая функция, которая должна иметь возможность обрабатывать более или менее любую строку:

>>> import itertools
>>> 
>>> def key_fun(s):
...     return (*(("",) if s and s[0].isdecimal() else ()), *(int(''.join(g)) if k else ''.join(g) for k, g in itertools.groupby(s, str.isdecimal)),)

Демонстрация (добавлено несколько случайных строк, которые не следуют шаблону):

>>> pprint(sorted(list_of_dwg + ['', '45', 'e'], key=key_fun))
['',
 '45',
 '\\\\pc_name\\AHL-4604-0002-1_FRONT COVER.dwg',
 '\\\\pc_name\\AHL-4604-0002-2_MASTER LIST.dwg',
 '\\\\pc_name\\AHL-4604-0002-3_LEGEND LIST.dwg',
 '\\\\pc_name\\AHL-4604-0002-4.dwg',
 '\\\\pc_name\\AHL-4604-0002-10.dwg',
 '\\\\pc_name\\AHL-4604-0002-11A.dwg',
 'e']

Вот что делает ключевая функция.Он группируется по десятичному / не десятичному типу и преобразует десятичные блоки.Одна проблема заключается в том, что мы должны всегда начинать с одного и того же вида блока, потому что Python3 не любит сравнивать числа и строки.Я решил добавить пустую строку, если первый символ десятичный.Как следствие, все, что начинается с числа, предшествует всему, что начинается с не числа.

>>> key_fun(list_of_dwg[0])
('\\\\pc_name\\AHL-', 4604, '-', 2, '-', 10, '.dwg')
0 голосов
/ 12 июня 2018

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

. *Функция 1005 * принимает ключевую функцию, которую вы можете использовать, чтобы сообщить sorted, как сортировать ваши элементы.В этом случае мы можем использовать регулярное выражение, чтобы найти последний номер в именах файлов и использовать его целочисленное значение для сортировки элементов.

In [18]: import re

In [19]: def keyfunc(item):
    ...:     return int(re.search(r'-(\d+)[^-]*$', item).group(1))
    ...: 
    ...: 

In [20]: sorted(list_of_dwg, key=keyfunc)
Out[20]: 
['\\\\pc_name\\AHL-4604-0002-1_FRONT COVER.dwg',
 '\\\\pc_name\\AHL-4604-0002-2_MASTER LIST.dwg',
 '\\\\pc_name\\AHL-4604-0002-3_LEGEND LIST.dwg',
 '\\\\pc_name\\AHL-4604-0002-4.dwg',
 '\\\\pc_name\\AHL-4604-0002-10.dwg',
 '\\\\pc_name\\AHL-4604-0002-11A.dwg']

Как вы можете видеть, в keyfunc мы предполагали, что естьвсегда соответствует нашему регулярному выражению без обработки каких-либо возможных исключений и / или с учетом других факторов для сортировки.Правильный способ обработки таких случаев - это использование try-except для правильной обработки различных исключений.

В качестве примера, скажем, мы хотим отсортировать элементы буквально по умолчаниюв тех случаях, когда наше регулярное выражение не может найти ожидаемое целое число в конце имени файла.В этом случае код вернет AttributeError, поскольку re.search() вернет None, а объект None не имеет атрибута group().Мы можем справиться с этой ситуацией просто следующим образом:

In [21]: def keyfunc(item):
    ...:     try:
    ...:         return int(re.search(r'-(\d+)[^-]*$', item).group(1))
    ...:     except AttributeError:
    ...:         return item
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...