Python:按字符串属性对对象列表进行排序

时间:2019-01-22 23:18:12

标签: python file sorting

我已经在一个文件夹中生成了许多图像文件(PNG)。每个名称都类似于“ img0.png”,“ img1.png”,...,“ img123164971.png”等。这些图像的顺序对我很重要,数字部分代表我需要检索它们之前的顺序。我将它们添加到html表单中。

这个问题为我提供了一个解决方案:Does Python have a built in function for string natural sort?

但是我不确定如何将其合并到我的特定代码中

imagedata = list()
files_and_dirs = Path(imagefolder).glob('**/*')
images = [x for x in files_and_dirs if x.is_file() and x.suffix == '.png']

for image in images:
    imagedata.append("<img src='{0}/{1}' width='200'>".format(imagefolder, image.name))

这些文件自然是按字母数字读取的,但这不是我想要的。 我有一种感觉,我可以简单地做一个images = sort_function(images),但是我不确定它到底是怎么做到的。我意识到我可以做到:

imagedata = list()
files_and_dirs = Path(barcodeimagefolder).glob('**/*')
images = [x.name for x in files_and_dirs if x.is_file() and x.suffix == '.png']
images = natural_sort(images)

for image in images:
    imagedata.append("<img src='{0}/{1}' width='200'>".format(imagefolder, image))

def natural_sort(l): 
    convert = lambda text: int(text) if text.isdigit() else text.lower() 
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] 
    return sorted(l, key = alphanum_key)

在链接中使用Mark Byers的解决方案。但是我后来需要实际图像本身的列表,当其中一个包含另一个中的所有数据时,具有两个列表似乎显得多余。相反,我非常想以这种方式根据图像文件的列表对它们进行排序。或者更好的是,如果可能的话,从该文件夹中读取它们。有什么建议吗?

编辑:我更改了标题,使其更加简洁,希望仍然准确。

2 个答案:

答案 0 :(得分:1)

假设您真的想严格按照单个文件的名称对文件进行“自然排序”,而不是使用完整路径(例如,“ zzz / image01.png”在“ aaa / image99.png”之前) ,(编辑我现在从注释中看到不是这种情况),一种方法是创建一个有序词典,其中键是文件名,然后这些值就是您最终要创建的“”标签。然后对字典键进行自然排序,并返回相应值的列表。

因此,使用一个包含3个虚构文件的简单列表,并为原始的natural_sort函数添加一个变体:

import collections
import re

def files_with_natural_sort(l):
    convert = lambda text: int(text) if text.isdigit() else text.lower()
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ]
    return [ l[newkey] for newkey in sorted(l, key = alphanum_key) ]

original_files = ["folder_c/file9.png", "folder_a/file11.png", "folder_b/file10.png"]

image_dict = collections.OrderedDict()

for file in original_files:
    [folder, filename] = file.split('/')
    image_dict[filename] = '<img src="%s" width="200">' % file

sorted_keys = files_with_natural_sort(image_dict)
print(sorted_keys)

这将输出:

['<img src="folder_c/file9.png" width="200">', '<img src="folder_b/file10.png"
    width="200">', '<img src="folder_a/file11.png" width="200">']

使用常规词典并使用该词典的.keys()列表可以解决此问题。但这仍然有效。至于尝试在阅读时创建所需顺序的文件列表,我想您可以为此进行一些花哨的气泡排序,但我真的不会为此感到汗颜。除非您有数百万个文件,否则我看不到使用多个列表的危害。

答案 1 :(得分:0)

您的意思是您只想对imagedata进行排序?不漂亮,但是尝试:

imagedata.sort(key=lambda x : int(re.search('(\d+)', re.search('(src=\'.+\/)', x)[0])[0]))

假设src='<something>/具有非数字前缀和非数字后缀,则内部正则表达式将获得<something>,而外部正则表达式将获得<something>中的数字。