Python 如何对格式不佳的伪数字字符串进行排序
我有两个渲染图像名称列表作为深度学习训练算法的输入,我需要首先将它们分组为相关的组(每组中有几个文件,具有不同的采样数,但对于一个场景也有几个组,相机角度不同) 当我看到以下类型的文件名时,就会出现问题: 所需排序:Python 如何对格式不佳的伪数字字符串进行排序,python,sorting,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_00000
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_000001.exr
Scene_1_Camera_0_000001.exr
Scene_1_Camera_0_131072.exr
Scene_1_Camera_131072.exr
问题是,排序是逐字符进行的,并且不知道可能同时存在摄影机和摄影机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++排序函数中通常可以使用的比较定制。 如果你能确定数字总是六位数长,你可以使用:
listOfFilenames.sort(key=(lambda s: s[-10:-4]))
这将从字符串扩展名前的最后六个字符中提取一部分,并按这些字符进行排序。如果可以确保数字始终为六位数,则可以使用:
listOfFilenames.sort(key=(lambda s: s[-10:-4]))
这将从扩展名之前的字符串的最后六个字符中提取一部分,并按这些字符进行排序。32000个条目并不多-文件大小无关紧要,因为您没有编辑文件本身 我可以想到几个选择:
32000条条目并不多——文件大小无关紧要,因为您不是在编辑文件本身 我可以想到几个选择:
当我回答我自己的问题时,我不太确定如何处理这个回答,但下面是: 杰姆坎贝尔的回答让我得出以下结论:
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
这将给出所需的排序顺序
谢谢大家的集思广益 当我回答自己的问题时,我不太确定如何处理这个回答,但下面是: 杰姆坎贝尔的回答让我得出以下结论:
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
这将给出所需的排序顺序
谢谢大家的集思广益 查看
natsort
软件包。除了“Camera”和“Camera\u 0”之外,还有其他摄像头吗?如果是这样,它们是否需要按数字排序,或者字符串排序可以吗?最后一个数字组是否总是6位数?我假设您希望将具有相同场景编号和摄影机编号的所有名称分组在一起。是这样吗?Yakym,我已经看过了,它很可能会立即解决我的问题,但我犹豫是否要走这条路,因为它需要安装一个软件包。我正在使用映射的网络驱动器在Windows上开发该脚本,但将在Linux上运行它,其中的文件是本机文件,并且我不一定能够控制Linux机器上的Python安装。因此,我更喜欢使用标准Python only.PM的解决方案,是的,有许多不同的摄像头,有各种各样的命名方案。这个例子只是例举了我在排序时遇到的特殊冲突。只要具有相同场景/摄影机的所有文件都分组在一起,摄影机的排序顺序就无关紧要。最后一个组当前总是6位数字,但我更喜欢保持它更灵活,这就是为什么我在正则表达式中使用{4,6}来实现这一点。查看natsort
包。除了“Camera”和“Camera\u 0”之外,还有其他摄像头吗?如果是这样,它们是否需要按数字排序,或者字符串排序可以吗?最后一个数字组是否总是6位数?我假设您希望将具有相同场景编号和摄影机编号的所有名称分组在一起。是这样吗?Yakym,我已经看过了,它很可能会立即解决我的问题,但我犹豫是否要走这条路,因为它需要安装一个软件包。我正在使用映射的网络驱动器在Windows上开发该脚本,但将在Linux上运行它,其中的文件是本机文件,并且我不一定能够控制Linux机器上的Python安装。因此,我更喜欢一个