Python 比较列表列表中的元组值?
我有一个Python 比较列表列表中的元组值?,python,python-3.x,list,tuples,Python,Python 3.x,List,Tuples,我有一个列表,如下所示: mylist=[[(1, 1)], [(1, 1), (1, 2)], [(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]] [[(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]] 现在,我想要的是将这个列表中的每个元素与所有其他元素进行比较,如果该元素是它所比较的元素的子集,那么应该将其弹出。例如,[(1,1)]是[(1,1)、(1,2)]的子集,然后应从列表中弹出
列表
,如下所示:
mylist=[[(1, 1)], [(1, 1), (1, 2)], [(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]]
[[(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]]
现在,我想要的是将这个列表中的每个元素与所有其他元素进行比较,如果该元素是它所比较的元素的子集,那么应该将其弹出。例如,[(1,1)]
是[(1,1)、(1,2)]
的子集,然后应从列表中弹出[(1,1)]
。类似地,[(1,1)、(1,2)]
是[(1,1)、(1,2)、(1,3)]
的子集,那么它也应该被弹出
在这种情况下,我们得到如下输出:
mylist=[[(1, 1)], [(1, 1), (1, 2)], [(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]]
[[(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]]
我试图寻找所有可能的答案,但没有一个是针对这个特殊的情况
到目前为止,我尝试了以下方法,但没有什么用处:
for i, e in enumerate(mylist):
mylist[i] = tuple(e)
mylist = list(set(mylist))
您需要从mylist
中删除列表,其中列表中的元组位于mylist
中的另一个列表中。通过分配给一个新列表,最容易做到这一点:
newlist=[]
对于i,枚举中的lst(mylist):
如果没有(所有(t在l中表示t在lst中)表示l在mylist[:i]+mylist[i+1:]):
newlist.append(lst)
或作为列表:
newlist=[lst代表i,lst在枚举(mylist)中,如果没有(all(t在l中代表t在lst中)代表l在mylist[:i]+mylist[i+1:])]
在这两种情况下,对于示例数据,输出为:
[
[(1, 1), (1, 2), (1, 3)],
[(1, 1), (1, 2), (1, 4)]
]
对于较大的列表,这可能会变慢,在这种情况下,您可以通过首先将mylist
中的条目映射到集合来加快速度:
mylist=[(1,1),(1,2)],[(1,1),(1,2),(1,3)],[(1,1),(1,2),(1,4)],[(1,1)]]
mylist=list(映射(集合,(mylist中l的元组(l)))
newlist=[list(lst)for i,lst in enumerate(mylist)如果没有(lst.issubset(l)for l in mylist[:i]+mylist[i+1:])]
您可以使用和执行以下示例中的比较:
感谢@Nick的建议,这是一个更详细的示例:
mylist=[[(1, 1)], [(1, 1), (1, 2)], [(1, 1), (1, 2), (1, 3)], [(1, 1),
(1, 2), (1, 4)]]
out = []
for k, elm in enumerate(mylist):
for elm2 in mylist[:k] + mylist[k + 1:]:
if frozenset(elm).issubset(elm2):
break
else:
out.append(elm)
print(out)
输出:
[[(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]]
来自@Nick和@ChihebNexus的解决方案都不是有效的
来自@Nick的答案要求时间复杂度为O(m^2 x n^2),而@ChihebNexus的答案要求时间复杂度为O(m^2 x n),其中m是输入列表的长度,n是子列表的平均长度
对于只需要时间复杂度为O(m x n)的方法,您可以创建一个dict,将每个元组项映射到该项出现在其中的一组子列表,请记住,这些子列表需要首先转换为元组才能成为可散列并添加到集合中:
mapping = {}
for lst in mylist:
for item in lst:
mapping.setdefault(item, set()).add(tuple(lst))
因此,通过示例输入,映射成为:
{(1, 1): {((1, 1),),
((1, 1), (1, 2)),
((1, 1), (1, 2), (1, 3)),
((1, 1), (1, 2), (1, 4))},
(1, 2): {((1, 1), (1, 2), (1, 3)), ((1, 1), (1, 2)), ((1, 1), (1, 2), (1, 4))},
(1, 3): {((1, 1), (1, 2), (1, 3))},
(1, 4): {((1, 1), (1, 2), (1, 4))}}
然后,通过建立项目到其所属子列表的映射,我们可以再次迭代子列表,并获取当前子列表中项目映射到的子列表集的交集,以便找到包含当前子列表中所有项目的子列表。如果有多个符合条件的子列表,这意味着当前子列表是其他符合条件的子列表的子集,并且我们可以通过将当前子列表从其项目映射到的所有集合中移除来从结果中移除当前子列表。在此过程中幸存下来的子列表将是我们希望在输出中使用的子列表,我们可以通过使用union操作聚合集合来获得这些子列表:
for lst in mylist:
if len(set.intersection(*map(mapping.get, lst))) > 1:
t = tuple(lst)
for item in lst:
mapping[item].remove(t)
print(set.union(*mapping.values()))
这将产生:
{((1, 1), (1, 2), (1, 3)), ((1, 1), (1, 2), (1, 4))}
如果确实需要问题中的确切数据类型,可以将其转换为列表列表:
list(map(list, set.union(*mapping.values())))
返回:
[[(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]]
@ChihebNexus您能解释一下for
循环中发生了什么吗。我很难理解它。@Junaid我们在列表上循环并获取当前索引。然后我们在同一个列表上再次循环,但是我们删除了第一个循环当前索引处的元素。然后,我们将第一个循环索引的第一个元素转换为forzenset
,并使用issubset
方法检查第一个元素是否是第二个元素的子集。