我有两个渲染图像名称列表作为深度学习训练算法的输入,我需要先将它们分组到相关的组中(每组中有几个文件,具有不同数量的样本,但也有几个组用于一个场景,相机角度不同。)
当我看到以下类型的文件名时,会出现问题:
期望的排序:
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 ++排序函数中通常可用的比较自定义类似的东西。
答案 0 :(得分:1)
32000个条目不是很多 - 文件大小并不重要,因为您自己并没有自己编辑文件。
我可以想到几个选项:
重命名列表中的条目。不是文件本身,而是您收集的列表。将_0附加到缺少它的条目,并且您可以轻松排序。
按最后6个字符(或最后一个' _'后面的所有字符)排序。您的文件名中已经存在可识别的模式,只是省略了与该模式不匹配的部分。
使用可以处理该条件的排序算法。 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]))
这需要在扩展名之前输入字符串的最后六个字符并按其排序。