如何对配方不合理的伪数字字符串进行排序

时间:2017-07-19 18:10:40

标签: python sorting

我有两个渲染图像名称列表作为深度学习训练算法的输入,我需要先将它们分组到相关的组中(每组中有几个文件,具有不同数量的样本,但也有几个组用于一个场景,相机角度不同。)

当我看到以下类型的文件名时,会出现问题:

期望的排序:

Scene_1_Camera_000001.exr
Scene_1_Camera_131072.exr
Scene_1_Camera_0_000001.exr
Scene_1_Camera_0_131072.exr

或:

Scene_1_Camera_0_000001.exr
Scene_1_Camera_0_131072.exr
Scene_1_Camera_000001.exr
Scene_1_Camera_131072.exr

但是,实际排序:

Scene_1_Camera_000001.exr
Scene_1_Camera_0_000001.exr
Scene_1_Camera_0_131072.exr
Scene_1_Camera_131072.exr

问题在于排序是逐个字符的,并且没有关于可能同时存在Camera和Camera_0(我无法控制这些名称,场景是历史的)这一事实的概念,以及因此,使用相机上的_0覆盖样本名称,从而将我的两个组分成三组。

我目前在另一个地方使用以下代码(减去错误检查以确保清晰度),并且可以想象在自定义排序功能中使用类似的东西,使用前缀作为主要排序键,并将样本号作为辅助,但是我担心这会非常低效。

    res = re.search("(.*_)([0-9]{4,6}).([a-zA-Z]{3})", beauty_file)
    prefix = res.group(1)
    #sample = res1.group(2)
    #suffix = res1.group(3)

有没有办法使用自定义排序功能,并且有效地执行此操作(有32000个5MB文件)?

[编辑1]

似乎我对所需的排序顺序不够清楚:它需要首先在场景/摄像机上进行排序,然后才对样本编号进行排序,即最后六位数是辅助密钥。否则我会将所有样本编号放在一起,无论场景和摄像机如何,这都不允许我将分组文件组合在一起。

[编辑2]

我更喜欢使用标准Python的解决方案,因为我可能无法在运行脚本的机器上安装软件包。由于功能强大的调试器,我正在Windows上开发。我想到了与模板化C ++排序函数中通常可用的比较自定义类似的东西。

3 个答案:

答案 0 :(得分:1)

32000个条目不是很多 - 文件大小并不重要,因为您自己并没有自己编辑文件。

我可以想到几个选项:

  1. 重命名列表中的条目。不是文件本身,而是您收集的列表。将_0附加到缺少它的条目,并且您可以轻松排序。

  2. 按最后6个字符(或最后一个' _'后面的所有字符)排序。您的文件名中已经存在可识别的模式,只是省略了与该模式不匹配的部分。

  3. 使用可以处理该条件的排序算法。 natsort是一种受欢迎的选择。

答案 1 :(得分:1)

当我回答我自己的问题时,我不太确定如何处理这个回复,但是这里有:

jmcampbell的回答让我得到以下结论:

def compare(item1, item2):
    res1 = re.search("(.*_)([0-9]{4,6}).([a-zA-Z]{3})", item1)
    if res1 == None or len(res1.groups()) != 3:
        return item1 < item2
    prefix1 = res1.group(1)
    sample1 = res1.group(2)

    res2 = re.search("(.*_)([0-9]{4,6}).([a-zA-Z]{3})", item2)
    if res2 == None or len(res2.groups()) != 3:
        return item1 < item2
    prefix2 = res2.group(1)
    sample2 = res2.group(2)

    if prefix1 < prefix2:
        return -1
    elif prefix1 > prefix2:
        return 1
    elif sample1 < sample2:
        return -1
    elif sample1 > sample2:
        return 1
    else:
        return 0

然后按如下方式调用排序函数:

beauty_files.sort(cmp=compare)

这将提供所需的排序顺序。

感谢大家的头脑风暴!

答案 2 :(得分:0)

如果您可以确定这些数字总是六位数,您可以使用:

listOfFilenames.sort(key=(lambda s: s[-10:-4]))

这需要在扩展名之前输入字符串的最后六个字符并按其排序。