python - 如何根据 Python 中类似定位的字符/模式对文件进行分组?
问题描述
我在不同文件夹的列表中有一组文件名,如下所示:
输入文件
['ABC.dat',
'ABC10.dat',
'ABC956.dat',
'ABC_DEF_1.dat',
'ABC_DEF_2.dat',
'ABC_DEF_3.dat',
'ABC10_DEF_1.dat',
'ABC10_DEF_2.dat',
'ABC10_DEF_3.dat',
'ABC956_DEF_1.dat',
'ABC956_DEF_2.dat',
'ABC956_DEF_3.dat',
'XYZ_ABC_1.dat',
'XYZ_ABC_2.dat',
'XYZ10_ABC_1.dat',
'XYZ10_ABC_2.dat',
'XYZ956_ABC_1.dat',
'XYZ956_ABC_2.dat',
'XYZ_PQR_JKL.dat',
'XYZ_PQR_JKL_1.dat',
'XYZ_PQR10_JKL.dat',
'XYZ_PQR10_JKL_1.dat',
'XYZ_PQR956_JKL.dat',
'XYZ_PQR956_JKL_1.dat']
我想将文件分组如下:
输出列表
[['ABC.dat', 'ABC10.dat', 'ABC956.dat'],
['ABC_DEF_1.dat', 'ABC10_DEF_1.dat.dat', 'ABC956_DEF_1.dat'],
['ABC_DEF_2.dat', 'ABC10_DEF_2.dat.dat', 'ABC956_DEF_2.dat'],
['ABC_DEF_3.dat', 'ABC10_DEF_3.dat.dat', 'ABC956_DEF_3.dat'],
['XYZ_ABC_1.dat', 'XYZ10_ABC_1.dat', 'XYZ956_ABC_1.dat'],
['XYZ_ABC_2.dat', 'XYZ10_ABC_2.dat', 'XYZ956_ABC_2.dat'],
['XYZ_PQR_JKL.dat', 'XYZ_PQR10_JKL.dat', 'XYZ_PQR956_JKL.dat'],
['XYZ_PQR_JKL_1.dat', 'XYZ_PQR10_JKL_1.dat', 'XYZ_PQR956_JKL_1.dat']]
也就是说应该根据文件的模式对文件进行分组。注意 DEF_1 和 DEF_2 必须单独分组。数字 10、956 是随机的,也就是说,它们事先是未知的。下面给出了一个 MWE,它基于从OP获得的前几个字母进行分组,我如何将它扩展到 DEF 的其他字母。
MWE
import os
import random
import errno
import itertools
from itertools import repeat
#--------------------------------------
# Main rename code
for root, dirs, files in os.walk('./input_folder'):
for dir in dirs:
print (dir)
output_files = [s for s in os.listdir(os.path.join(root,dir)) if s.endswith('.dat')]
groups = [list(g) for _, g in itertools.groupby(sorted(output_files), lambda x: x[0:2])] # obtained from Aaron's answer https://gis.stackexchange.com/a/206053
print (groups)
解决方案
您可以使用递归:
import re
def is_match(a, b):
a, b = re.sub('\s\w+\.dat$', '', a).split(), re.sub('\s\w+\.dat$', '', b).split()
if len(a) != len(b):
return False
return all(c == d if not c.isdigit() and not d.isdigit() else c.isdigit() and d.isdigit() for c, d in zip(a, b))
def group_vals(d, _current = []):
if _current:
yield _current
if d:
_start, *_d = d
yield from group_vals([i for i in _d if not is_match(_start, i)], [_start, *[i for i in _d if is_match(_start, i)]])
files = list(filter(None, _input.split('\n')))
print(list(group_vals(files)))
输出:
[['ABC 956.dat', 'ABC 114.dat', 'ABC 577.dat', 'ABC 782.dat'],
['ABC DEF 10.dat', 'ABC DEF 23.dat', 'ABC DEF 27.dat', 'ABC DEF 54.dat'],
['XYZ-ABC 158.dat', 'XYZ-ABC 221.dat', 'XYZ-ABC 668.dat', 'XYZ-ABC 919.dat'],
['ABC 127 JKL.dat', 'ABC 272 JKL.dat', 'ABC 462 JKL.dat', 'ABC 707 JKL.dat'],
['ABC 137 XYZ 97.dat', 'ABC 164 XYZ 25.dat', 'ABC 418 XYZ 13.dat', 'ABC 913 XYZ 11.dat'],
['ABC 258 PQR0 0.dat', 'ABC 551 PQR0 3.dat', 'ABC 606 PQR0 5.dat', 'ABC 654 PQR0 2.dat'],
['ABC 542 PQR1 4.dat', 'ABC 234 PQR1 2.dat', 'ABC 432 PQR1 7.dat', 'ABC 766 PQR1 5.dat']]
推荐阅读
- php - 使用旧版本数据库的新版本 Laravel 项目
- wireshark - 将wireshark与ns3一起使用
- libgdx - 在 libgdx 中设置文本 alpha 的最佳方法
- python - 试图找到这种特殊情况的正则表达式?我也可以在不创建组的情况下解析它吗?
- php - 如何在(高级)自定义字段更新上添加订单注释?
- ip-camera - 在霍尼韦尔 HBL6GR2 上查找实时快照的 URL
- php - 如何在函数中使用动态变量与 PHP 和 MySQL 中的查询
- java - 如何使用 GridBagLayout 实现这种布局?
- mule - 在 mulesoft 中调用流的 mule 推荐方法是什么?
- tsql - 在 T-SQL 查询中选择多个计数字段