繁体   English   中英

如何自然地对 Python 中的 Pathlib 对象进行排序?

[英]How to Naturally Sort Pathlib objects in Python?

我正在尝试在./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")

当前 output:

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  

预期 Output:

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

我尝试了在副本中找到的解决方案,但它们不起作用,因为 pathlib 文件是 class 对象,而不是字符串。 当我打印它们时,它们只显示为文件名。

例如:

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')

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

natsorted(list_of_pathlib_objects, key=str)

可以使用natsort 库pip install natsort 。它应该看起来也很简单。
[,这行得通。 至少针对版本 5.5 和 7.1(当前)进行了测试]

from natsort import natsorted

image_list = Path('./pages').glob('*.jpg')
# 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 ])]

请注意, sorted不会对您的数据进行排序,而是返回一个新列表,因此您必须对其 output 进行迭代。

为了获得您的排序键,即文件名末尾的 integer 值:

  • 您可以首先获取路径的主干,这是它的最终组件,没有扩展名(例如, '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)

样品 output:

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

问题并不像听起来那么简单,“自然”排序可能非常具有挑战性,尤其是对于潜在的任意输入字符串,例如,如果您的数据中有“69_helloKitty.jpg”怎么办? 不久前我使用https://github.com/SethMorton/natsort解决了类似的问题,也许它可以帮助你。

这样使用...

from pathlib import Path

- 按名称排序:

sorted(Path('anywhere/you/want').glob('*.jpg'))

- 按修改时间排序:

import os
sorted(Path('anywhere/you/want').glob('*.jpg'), key=os.path.getmtime)

- 按大小排序:

import os
sorted(Path('anywhere/you/want').glob('*.jpg'), key=os.path.getsize)

等等

提示:因为文件名也是由您创建的。 写入文件名并添加填充零,例如:

for i in range(100):        
    with open('filename'+f'_{i:03d}','wb'):  # py3.6+ fstring        
       # write your file stuff...
    # py3.3+ 'filename'+'_{:03d}'.format(i) for str.format()
 ...
 'filename_007',
 'filename_008',
 'filename_009',
 'filename_010',
 'filename_011',
 'filename_012',
 'filename_013',
 'filename_014',
 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM