繁体   English   中英

比较列表列表中的元组值?

[英]Comparing tuple values inside list of lists?

我有一个list如下:

mylist=[[(1, 1)], [(1, 1), (1, 2)], [(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]]

现在,我想要的是将此列表中的每个元素与所有其他元素进行比较,如果该元素是与之比较的元素的子集,则应将其弹出。 例如, [(1, 1)][(1, 1), (1, 2)]的子集,那么[(1, 1)]应该从list中弹出。 同样, [(1, 1), (1, 2)][(1, 1), (1, 2), (1, 3)]的子集,那么它也应该被弹出。

在这种情况下,我们得到 output 如下:

[[(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中删除any列表,其中列表中的all元组都存在于mylist的另一个列表中。 这最容易通过分配给一个新列表来完成:

newlist = []
for i, lst in enumerate(mylist):
    if not any(all(t in l for t in lst) for l in mylist[:i] + mylist[i+1:]):
        newlist.append(lst)

或作为列表理解:

newlist = [lst for i, lst in enumerate(mylist) if not any(all(t in l for t in lst) for l in mylist[:i] + mylist[i+1:])]

在这两种情况下,对于您的示例数据,output 是:

[
 [(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(map(set, (tuple(l) for l in mylist)))
newlist = [list(lst) for i, lst in enumerate(mylist) if not any(lst.issubset(l) for l in mylist[:i] + mylist[i+1:])]

您可以使用frozenset.issubset并像以下示例一样进行比较:

感谢@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)

Output:

[[(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]]

@Nick 和 @ChihebNexus 的解决方案都没有效率。

@Nick 的答案需要O(m ^ 2 xn ^ 2)的时间复杂度,而@ChihebNexus 的答案需要O(m ^ 2 xn)的时间复杂度,其中m是输入列表的长度, n是子列表的平均长度。

对于只需要O(mxn)时间复杂度的方法,您可以创建一个 dict 将每个元组项目映射到该项目出现的一组子列表,请记住这些子列表需要转换元组首先变为可散列并添加到集合中:

mapping = {}
for lst in mylist:
    for item in lst:
        mapping.setdefault(item, set()).add(tuple(lst))

因此,使用您的示例输入, mapping变为:

{(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))}}

然后通过建立项目与其所属子列表的映射,我们可以再次遍历子列表,并取当前子列表 map 中的项目到的子列表集合的交集,在为了找到包含当前子列表中所有项目的子列表。 如果有多个这样的符合条件的子列表,则意味着当前子列表是其他符合条件的子列表的子集,我们可以通过将当前子列表从结果中删除将其项目 map 设置为。 在这个过程中幸存下来的子列表将是我们想要的 output 中的子列表,我们可以通过使用联合操作聚合集合来获得:

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)]]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM