如何在 Python 中自然排序 Pathlib 对象?

Pra*_*ani 13 python python-3.x pathlib

我正在尝试在目录中创建一个排序的文件列表./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")

Run Code Online (Sandbox Code Playgroud)

电流输出:

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  
Run Code Online (Sandbox Code Playgroud)

预期输出:

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
Run Code Online (Sandbox Code Playgroud)

我已经尝试了重复中找到的解决方案,但它们不起作用,因为 pathlib 文件是类对象,而不是字符串。当我打印它们时,它们仅显示为文件名。

例如:

print(filename) # pages/page_1.jpg  
print(type(filename)) # <class 'pathlib.PosixPath'>
Run Code Online (Sandbox Code Playgroud)

最后,这是工作代码。谢谢大家。

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')
Run Code Online (Sandbox Code Playgroud)

小智 6

只是为了后代,也许这更简洁?

natsorted(list_of_pathlib_objects, key=str)
Run Code Online (Sandbox Code Playgroud)


Jaj*_*aja 5

可以使用natsort lib ( pip install natsort。它看起来也很简单。
[!这有效,至少在版本 5.5 和 7.1 (当前) 上进行了测试]

from natsort import natsorted

image_list = Path('./pages').glob('*.jpg')
image_list = natsorted(image_list, key=str)

# Or convert list of paths to list of string and (naturally)sort it, then convert back to list of paths
image_list = [Path(p) for p in natsorted([str(p) for p in image_list ])]
Run Code Online (Sandbox Code Playgroud)


Thi*_*lle 4

请注意,这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)
Run Code Online (Sandbox Code Playgroud)

示例输出:

pages/ma_page_2.jpg
pages/ma_page_11.jpg
pages/ma_page_13.jpg
pages/ma_page_20.jpg
Run Code Online (Sandbox Code Playgroud)