Как естественным образом отсортировать объекты Pathlib в Python? - PullRequest
1 голос
/ 09 октября 2019

Я пытаюсь создать отсортированный список файлов в каталоге ./pages. Это то, что у меня есть:

import numpy as np
from PIL import Image
import glob
from pathlib import Path


# sorted( l, key=lambda a: int(a.split("-")[1]) )
image_list = []

for filename in Path('./pages').glob('*.jpg'):
#     sorted( i, key=lambda a: int(a.split("_")[1]) )
#     im=Image.open(filename)
    image_list.append(filename)

print(*image_list, sep = "\n")

токовый выход:

pages/page_1.jpg  
pages/page_10.jpg  
pages/page_11.jpg  
pages/page_12.jpg  
pages/page_2.jpg  
pages/page_3.jpg  
pages/page_4.jpg  
pages/page_5.jpg  
pages/page_6.jpg  
pages/page_7.jpg  
pages/page_8.jpg  
pages/page_9.jpg  

Ожидаемый вывод:

pages/page_1.jpg   
pages/page_2.jpg  
pages/page_3.jpg  
pages/page_4.jpg  
pages/page_5.jpg  
pages/page_6.jpg  
pages/page_7.jpg  
pages/page_8.jpg  
pages/page_9.jpg  
pages/page_10.jpg  
pages/page_11.jpg  
pages/page_12.jpg

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

Например:

print(filename) # pages/page_1.jpg  
print(type(filename)) # <class 'pathlib.PosixPath'>

Наконец, это рабочий код. Спасибо всем.

from pathlib import Path
import numpy as np
from PIL import Image
import natsort

def merge_to_single_image():
    image_list1 = []
    image_list2 = []
    image_list3 = []
    image_list4 = []

    for filename in Path('./pages').glob('*.jpg'):
        image_list1.append(filename)

    for i in image_list1:
        image_list2.append(i.stem)
    #     print(type(i.stem))

    image_list3 = natsort.natsorted(image_list2, reverse=False)

    for i in image_list3:
        i = str(i)+ ".jpg"
        image_list4.append(Path('./pages', i))

    images = [Image.open(i) for i in image_list4]
    # for a vertical stacking it is simple: use vstack
    images_combined = np.vstack(images)
    images_combined = Image.fromarray(images_combined)
    images_combined.save('Single_image.jpg')

Ответы [ 2 ]

0 голосов
/ 10 октября 2019

Проблема не так проста, как кажется, «естественная» сортировка может быть довольно сложной, особенно с потенциальными произвольными входными строками, например, что если в ваших данных есть «69_helloKitty.jpg»? Я использовал https://github.com/SethMMorton/natsort некоторое время назад для аналогичной проблемы, может быть, это поможет вам.

0 голосов
/ 09 октября 2019

Обратите внимание, что sorted не сортирует ваши данные на месте, но возвращает новый список, поэтому вы должны выполнить итерации по его выводу.

Чтобы получить ключ сортировки, который является целым числомзначение в конце вашего имени файла:

  • Сначала вы можете взять стебель вашего пути, который является его последним компонентом без расширения (например, 'page_13').

  • Затем лучше разделить его один раз справа, чтобы быть в безопасности, если ваше имя файла содержит другие подчеркивания в первой части, например 'some_page_33.jpg'.

  • После преобразования в int у вас есть ключ для сортировки.

Итак, ваш код может выглядеть следующим образом:

for filename in sorted(Path('./pages').glob('*.jpg'), 
                       key=lambda path: int(path.stem.rsplit("_", 1)[1])):

    print(filename)

Пример вывода:

pages/ma_page_2.jpg
pages/ma_page_11.jpg
pages/ma_page_13.jpg
pages/ma_page_20.jpg
...