Как сортировать объектные файлы «WindowsPath» естественным путем - PullRequest
1 голос
/ 07 апреля 2020

Я перебираю файлы в каталоге, используя Path (). Glob (), и он не перебирает в правильном естественном порядке. Например, это повторяется так:

[WindowsPath('C:/Users/HP/Desktop/P1/dataP1/SAMPLED_NORMALIZED/P1_Cor.csv'),
 WindowsPath('C:/Users/HP/Desktop/P10/dataP10/SAMPLED_NORMALIZED/P10_Cor.csv'),
 WindowsPath('C:/Users/HP/Desktop/P11/dataP11/SAMPLED_NORMALIZED/P11_Cor.csv'),
 WindowsPath('C:/Users/HP/Desktop/P12/dataP12/SAMPLED_NORMALIZED/P12_Cor.csv'),
# ...and so on from P1 to P30

Когда я хочу, чтобы оно повторялось так: P1, P2, P3 и т. д.

Я попытался использовать приведенный ниже код, но это дает мне ошибка:

from pathlib import Path

file_path = r'C:/Users/HP/Desktop'

files = Path(file_path).glob(file)
sorted(files, key=lambda name: int(name[10:]))

, где 10 - это просто тривиальное число, когда я пытаюсь использовать код.

Ошибка:

TypeError: 'WindowsPath' object is not subscriptable

В конечном итоге, я хочу чтобы перебрать файлы и сделать что-то с каждым файлом:

from pathlib import Path

for i, fl in enumerate(Path(file_path).glob(file)):
    # do something

Я даже попробовал библиотеку natsort, но она не упорядочивает файлы правильно в итерации. Я пробовал:

from natsort import natsort_keygen, ns
natsort_key1 = natsort_keygen(key=lambda y: y.lower())
from natsort import natsort_keygen, ns
natsort_key2 = natsort_keygen(alg=ns.IGNORECASE)

Два приведенных выше кода по-прежнему дают мне P1, P10, P11 и т. Д.

Любая помощь действительно будет оценена.

Ответы [ 3 ]

2 голосов
/ 07 апреля 2020

Если вы хотите отсортировать по цифрам в имени файла, вы можете использовать атрибут Path.name и регулярное выражение, которое извлекает цифры.

from pathlib import Path
import re

file_path = r'C:/Users/HP/Desktop/P1/dataP1/SAMPLED_NORMALIZED/'

def _p_file_sort_key(file_path):
    """Given a file in the form P(digits)_cor.csv, return digits as an int"""
    return int(re.match(r"P(\d+)", file_path.name).group(1))

files = sorted(Path(file_path).glob("P*_Cor.csv"), key=_p_file_sort_key)
1 голос
/ 07 апреля 2020

Использование natsort работает для сортировки этих данных, но вы должны указать ей, как извлечь строку из объекта Path (по умолчанию это не делается для повышения производительности).

In [2]: from pathlib import Path                                                                                    

In [3]: import natsort                                                                                              

In [4]: a = [Path('C:/Users/HP/Desktop/P1/dataP1/SAMPLED_NORMALIZED/P1_Cor.csv'),
             Path('C:/Users/HP/Desktop/P10/dataP10/SAMPLED_NORMALIZED/P10_Cor.csv'),
             Path('C:/Users/HP/Desktop/P2/dataP2/SAMPLED_NORMALIZED/P2_Cor.csv')]                                                                       

In [5]: natsort.natsorted(a, key=str)                                                                                      
Out[5]: 
[PosixPath('C:/Users/HP/Desktop/P1/dataP1/SAMPLED_NORMALIZED/P1_Cor.csv'),
 PosixPath('C:/Users/HP/Desktop/P2/dataP2/SAMPLED_NORMALIZED/P2_Cor.csv'),
 PosixPath('C:/Users/HP/Desktop/P10/dataP10/SAMPLED_NORMALIZED/P10_Cor.csv')]

In [6]: natsort.natsorted(a, alg=natsort.PATH)
Out[6]: 
[PosixPath('C:/Users/HP/Desktop/P1/dataP1/SAMPLED_NORMALIZED/P1_Cor.csv'),
 PosixPath('C:/Users/HP/Desktop/P2/dataP2/SAMPLED_NORMALIZED/P2_Cor.csv'),
 PosixPath('C:/Users/HP/Desktop/P10/dataP10/SAMPLED_NORMALIZED/P10_Cor.csv')]

Первая опция преобразует все Path объекты в строку, которую natsort знает, как обрабатывать. Это работает для ваших данных.

Второй параметр включает алгоритм natsort PATH, который автоматически корректно обрабатывает Path объекты, а также добавляет более надежную обработку для угловых случаев, распространенных в файле. системные пути.


Полное раскрытие, я natsort автор.

0 голосов
/ 07 апреля 2020

Вы можете вызвать str для объекта Path или использовать as_posix().

from pathlib import Path

for fn in sorted([str(p) for p in Path(file_path).glob('*.csv')]):
    # do something with fn

for fn in sorted([p.as_posix() for p in Path(file_path).glob('*.csv')]):
    # do something with fn

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