我有一个字符串分组列表,看起来像这样,这些组中的列表总是包含5个元素:
text_list = [['aaa','bbb','ccc','ddd','eee'],
['fff','ggg','hhh','iii','jjj'],
['xxx','mmm','ccc','bbb','aaa'],
['fff','xxx','aaa','bbb','ddd'],
['aaa','bbb','ccc','ddd','eee'],
['fff','xxx','aaa','ddd','eee'],
['iii','xxx','ggg','jjj','aaa']]
目标很简单,将所有相似的列表按前3个元素分组,然后与其他组中的所有元素进行比较。
所以从上面的例子中,输出可能看起来像这样(输出是列表的索引):[[0,2,4],[3,5]]
请注意,如果存在另一个包含相同元素但顺序不同的列表,则如何删除
我写了下面的代码来提取组,但他们会返回重复,我不确定如何进行。我还认为这可能不是最有效的提取方法,因为实际列表可以包含多达数百万个组:
grouped_list = []
for i in range(0,len(text_list)):
int_temp = []
for m in range(0,len(text_list)):
if i == m:
continue
bool_check = all( x in text_list[m] for x in text_list[i][0:3])
if bool_check:
if len(int_temp) == 0:
int_temp.append(i)
int_temp.append(m)
continue
int_temp.append(m)
grouped_list.append(int_temp)
## remove index with no groups
grouped_list = [x for x in grouped_list if x != []]
有更好的方法来做这件事吗?之后如何删除重复组?谢谢你。
编辑:
为了更清楚,我想检索彼此相似但只使用其他列表的前3个元素的列表。例如,使用列表A中的前3个元素,检查列表B、C、D……包含列表a中的所有3个元素,对整个列表重复操作,然后删除所有包含重复元素的列表。
您可以构建一组frozensets来跟踪组的索引,其中前3项是其余成员的子集:
groups = set()
sets = list(map(set, text_list))
for i, lst in enumerate(text_list):
groups.add(frozenset((i, *(j for j, s in enumerate(sets) if set(lst[:3]) <= s))))
print([sorted(group) for group in groups if len(group) > 1])
如果输入列表很长,创建一组所有子列表的前3个项目的冻结集并使用该集合过滤每个子列表中3个项目的所有组合会更快,这样时间复杂度基本上与输入列表呈线性关系,而不是二次关系,尽管生成组合的开销:
from itertools import combinations
sets = {frozenset(lst[:3]) for lst in text_list}
groups = {}
for i, lst in enumerate(text_list):
for c in map(frozenset, combinations(lst, 3)):
if c in sets:
groups.setdefault(c, []).append(i)
print([sorted(group) for group in groups.values() if len(group) > 1])