如何将列表中类似命名的元素分组为python中的元组?

时间:2017-09-19 06:57:17

标签: python python-3.x list tuples

我已经读过python列表中目录中所有文件的名称,如下所示:

files = ['ch1.txt', 'ch2.txt', 'ch3_1.txt', 'ch4_2.txt', 'ch3_2.txt', 'ch4_1.txt'] 

我想要做的是将类似的文件分组为列表中的元组。上面的例子看起来应该是

files_grouped = ['ch1.txt', 'ch2.txt', ('ch3_1.txt', 'ch3_2.txt'), ('ch4_1.txt', 'ch4_2.txt')]

我尝试过的一种方法是将我需要分组的元素从列表中分离出来,如此

groups = tuple([file for file in files if '_' in file])
single = [file for file in files if not '_' in file]

我会创建一个附加两者的新列表。但是,如何创建groups作为ch3ch4的元组列表,而不是[('ch3_1.txt', 'ch3_2.txt'), ('ch4_1.txt', 'ch4_2.txt')]而不是一个大元组?

3 个答案:

答案 0 :(得分:3)

这些答案都没有为您提供适用于任何类型文件名的通用解决方案。我想你应该使用正则表达式,如果你想考虑到这一点。

import itertools
import re

sorted_files = sorted(files, key=lambda x: re.findall('(\d+)_(\d+)', x))    
out = [list(g) for _, g in itertools.groupby(sorted_files, 
                       key=lambda x: re.search('\d+', x).group() )]

print(out)
[['ch1.txt'],
 ['ch2.txt'],
 ['ch3_1.txt', 'ch3_2.txt'],
 ['ch4_1.txt', 'ch4_2.txt']]

请注意,这适用于任何命名格式,而不仅仅是chX_X

如果您希望输出采用所描述的确切格式,您可以进行一些额外的后期处理:

out = [o[0] if len(o) == 1 else tuple(o) for o in out]
print(out)
['ch1.txt', 'ch2.txt', ('ch3_1.txt', 'ch3_2.txt'), ('ch4_1.txt', 'ch4_2.txt')]

正则表达式详细信息

第一个正则表达式按章节和小节进行排序。

(       # first group 
\d+     # 1 or more digits
)
_       # literal underscore
(       # second group
\d+     # 1 or more digits
)

第二个正则表达式组仅按章节部分 - 所有具有相同部分的章节组合在一起。

答案 1 :(得分:2)

您可以使用字典(或者,更简单地初始化collections.defaultdict

from collections import defaultdict
from pprint import pprint

files = ['ch1.txt', 'ch2.txt', 'ch3_1.txt', 'ch4_2.txt', 'ch3_2.txt', 'ch4_1.txt']

grouped = defaultdict(list)  # create an empty list for not existent entries

for f in files:
    key = f[:3]
    grouped[key].append(f)

pprint(grouped)

结果:

defaultdict(<class 'list'>,
            {'ch1': ['ch1.txt'],
             'ch2': ['ch2.txt'],
             'ch3': ['ch3_1.txt', 'ch3_2.txt'],
             'ch4': ['ch4_2.txt', 'ch4_1.txt']})

如果你想要你的元组列表,你可以这样做:

grouped = [tuple(l) for l in grouped.values()]

哪个是

[('ch1.txt',),
 ('ch2.txt',),
 ('ch3_1.txt', 'ch3_2.txt'),
 ('ch4_2.txt', 'ch4_1.txt')]

答案 2 :(得分:1)

也许您可以对文件名列表进行排序,然后使用groupby()执行此操作:

e.g。

from itertools import groupby

files = ['ch1.txt', 'ch2.txt', 'ch3_1.txt', 'ch4_2.txt', 'ch3_2.txt', 'ch4_1.txt']

print([tuple(g) for k,g in groupby(sorted(files),key=lambda x : x[:-4].split("_")[0])])

结果:

[('ch1.txt',), ('ch2.txt',), ('ch3_1.txt', 'ch3_2.txt'), ('ch4_1.txt', 'ch4_2.txt')]

希望这有帮助。