检查列表列表中是否存在列表的最快方法

时间:2018-05-24 13:08:46

标签: python list set

我有一个清单

a=[[1,2,3,4,5,6],[7,8,9,10,11,12]]   

检查另一个列表a中是否存在b中的任何列表的最快方法是什么?

b=[[5, 9, 25, 31, 33, 36],[7,8,9,10,11,12],[10, 13, 22, 24, 33, 44]]

如果b中存在a中的任何列表,我想将其删除。我目前正在使用此代码:

for each in a:
    for item in b:
        if set(each).issubset(item)
            a.remove(each)

这可行,但在处理大型列表时速度很慢,所以想知道是否有更好的方法。上面的代码给出了以下结果:

print(a)
[[1, 2, 3, 4, 5, 6]]

我并不担心订单,例如,如果a中的列表是[1,2,3,4,5,6]我希望在列表[1,2,3,4,5,6][3,4,1,6,2,5]等时删除它在列表b中。

3 个答案:

答案 0 :(得分:3)

list comprehensionset一起使用。

<强>实施例

a=[[1,2,3,4,5,6],[7,8,9,10,11,12]]  
b=[[5, 9, 25, 31, 33, 36],[7,8,9,10,11,12],[10, 13, 22, 24, 33, 44]]

setA = set(map(tuple, a))
setB = set(map(tuple, b))

print([i for i in setA if i not in setB])

<强>输出:

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

答案 1 :(得分:1)

使用set.difference

可以实现功能性解决方案
res = set(map(tuple, a)).difference(set(map(tuple, b)))

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

<强>解释

  1. 由于list不是哈希类型,因此我们将子列表转换为类型tuple,它们是不可变且可清除的,例如set(map(tuple, a))
  2. 然后使用set.difference获取2个结果集之间的差异。

答案 2 :(得分:0)

如果您不关心元素顺序和频率,即将列表视为无序集合,那么可能您的解决方案几乎是正确的(删除元素,而迭代相同的列表可能不是最好的主意),两个严重次优。

首先,您目前将每个b的元素转换为一个集合,每个元素一次。我想知道Python编译器是否可以优化重复的工作,至少你可以尝试自己做。

接下来,您不需要错误地和平方地删除元素以简单地过滤它们。

faster_b = [frozenset(x) for x in b]

def not_in_b(list):
    l = frozenset(list)
    for x in faster_b:
        if l <= x: return False
    return True

print(list(filter(not_in_b, a)))

这个可能更快。

$ python3
Python 3.6.5 (default, May 11 2018, 04:00:52) 
[GCC 8.1.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> a=[[1,2,3,4,5,6],[7,8,9,10,11,12]]
>>> b=[[5, 9, 25, 31, 33, 36],[7,8,9,10,11,12],[10, 13, 22, 24, 33, 44]]
>>> faster_b = [frozenset(x) for x in b]
>>> 
>>> def not_in_b(list):
...     l = frozenset(list)
...     for x in faster_b:
...         if l <= x: return False
...     return True
... 
>>> print(list(filter(not_in_b, a)))
[[1, 2, 3, 4, 5, 6]]
>>> a=[[1, 1, 2, 3]]
>>> b=[[7, 3, 2, 1], [4, 5, 6]]
>>> faster_b = [frozenset(x) for x in b]
>>> print(list(filter(not_in_b, a)))
[]
>>> a=[[1, 1, 2, 3], [42, 5, 6]]
>>> print(list(filter(not_in_b, a)))
[[42, 5, 6]]