Сортировка файловых путей по расширению в python - PullRequest
0 голосов
/ 18 февраля 2019

Я хочу отсортировать этот список таким образом, чтобы .log был первым файлом, а файл .gz - в порядке убывания

my_list = [
     '/abc/a.log.1.gz',
     '/abc/a.log',
     '/abc/a.log.gz',
     '/abc/a.log.30.gz',
     '/abc/a.log.2.gz',
     '/abc/a.log.5.gz',
     '/abc/a.log.3.gz',
     '/abc/a.log.6.gz',
     '/abc/a.log.4.gz',
     '/abc/a.log.12.gz',
     '/abc/a.log.10.gz',
     '/abc/a.log.8.gz',
     '/abc/a.log.14.gz',
     '/abc/a.log.29.gz'
]

Ожидаемый результат:

my_list = ['/abc/a.log',
        '/abc/a.log.gz',
        '/abc/a.log.30.gz',
        '/abc/a.log.29.gz',
        '/abc/a.log.29.gz',
        '/abc/a.log.14.gz',
        '/abc/a.log.12.gz',
        '/abc/a.log.10.gz',
        '/abc/a.log.8.gz',
        '/abc/a.log.6.gz',
        '/abc/a.log.5.gz',
        '/abc/a.log.4.gz',
        '/abc/a.log.3.gz',
        '/abc/a.log.2.gz'
        '/abc/a.log.1.gz']

Мое решение: импорт ОС

def get_sort_keys(filepath):
    split_file_path = os.path.splitext(filepath)
    sort_key = (split_file_path[1], *os.path.splitext(split_file_path[0]))
    return (sort_key[0], sort_key[1], int(sort_key[2].strip(".")) if sort_key[2] else 0)

print(sorted(my_list, key=get_sort_keys, reverse=True))

Получение ошибки:

ValueError: invalid literal for int() with base 10: 'log'

Ответы [ 3 ]

0 голосов
/ 18 февраля 2019

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

def try_convert(x):
    y = x.rsplit('.', 2)[-2]
    return ('log' not in x, int(y) if y.isdigit() else float('inf'), x)

sorted(my_list, key=try_convert, reverse=True)

['/abc/a.log.gz',
 '/abc/a.log',
 '/abc/a.log.30.gz',
 '/abc/a.log.29.gz',
 '/abc/a.log.14.gz',
 '/abc/a.log.12.gz',
 '/abc/a.log.10.gz',
 '/abc/a.log.8.gz',
 '/abc/a.log.6.gz',
 '/abc/a.log.5.gz',
 '/abc/a.log.4.gz',
 '/abc/a.log.3.gz',
 '/abc/a.log.2.gz',
 '/abc/a.log.1.gz']

Функция гарантирует, что имена файлов без целочисленного компонента будут упорядочены последними (сначала, если вы сортируетепо убыванию).Кроме того, все файлы ".log" идут первыми.

0 голосов
/ 18 февраля 2019

Или используйте:

>>> sorted(my_list,key=lambda x: int(x.split('.')[2]) if x.split('.')[2].isdigit() else 31,reverse=True)
['/abc/a.log.gz', '/abc/a.log.30.gz', '/abc/a.log.29.gz', '/abc/a.log.14.gz', '/abc/a.log.12.gz', '/abc/a.log.10.gz', '/abc/a.log.8.gz', '/abc/a.log.6.gz', '/abc/a.log.5.gz', '/abc/a.log.4.gz', '/abc/a.log.3.gz', '/abc/a.log.2.gz', '/abc/a.log.1.gz']
>>> 

Обновленный вопрос:

>>> sorted(my_list,key=lambda x: int(x.split('.')[-2]) if x.split('.')[-2].isdigit() else 31,reverse=True)
['/abc/a.log', '/abc/a.log.gz', '/abc/a.log.30.gz', '/abc/a.log.29.gz', '/abc/a.log.14.gz', '/abc/a.log.12.gz', '/abc/a.log.10.gz', '/abc/a.log.8.gz', '/abc/a.log.6.gz', '/abc/a.log.5.gz', '/abc/a.log.4.gz', '/abc/a.log.3.gz', '/abc/a.log.2.gz', '/abc/a.log.1.gz']
>>> 
0 голосов
/ 18 февраля 2019

Вы пытаетесь передать строку 'log' в int().

Затем она не может преобразовать это в int и вызывает ValueError: invalid literal for int() with base 10: 'log'

Это происходит вздесь return (sort_key[0], sort_key[1], int(sort_key[2].strip(".")) if sort_key[2] else 0)

Попробуйте использовать блок try catch для преобразования

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...