关于python:删除一个列表中出现的所有元素

Remove all the elements that occur in one list from another

假设我有两个列表,l1l2。我想执行l1 - l2,它返回l1的所有元素,而不是l2中的元素。

我可以想到一个简单的循环方法来实现这一点,但这将是非常低效的。做这件事的方法是什么?

例如,如果我有l1 = [1,2,6,8] and l2 = [2,3,5,8]l1 - l2应该返回[1,6]


Python有一个称为列表理解的语言特性,非常适合让这类事情变得非常简单。以下语句完全满足您的需要,并将结果存储在l3中:

1
l3 = [x for x in l1 if x not in l2]

l3将包含[1, 6]

希望这有帮助!


一种方法是使用集合:

1
2
>>> set([1,2,6,8]) - set([2,3,5,8])
set([1, 6])


扩展到油炸圈饼的答案和其他答案,通过使用生成器理解而不是列表理解,以及使用set数据结构(因为in运算符在列表上是O(n),而在集合上是O(1),可以获得更好的结果。

这里有一个对你有用的函数:

1
2
3
def filter_list(full_list, excludes):
    s = set(excludes)
    return (x for x in full_list if x not in s)

结果将是一个iterable,它将懒惰地获取筛选列表。如果您需要一个真正的列表对象(例如,如果您需要对结果执行EDOCX1[5]),那么您可以轻松地构建这样的列表:

1
filtered_list = list(filter_list(full_list, excludes))

使用python集类型。那将是最严重的Python。:)

而且,由于它是本地的,所以它也应该是最优化的方法。

见:

http://docs.python.org/library/stdtypes.html设置

http://docs.python.org/library/sets.htm(对于旧版python)

1
2
3
4
5
6
# Using Python 2.7 set literal format.
# Otherwise, use: l1 = set([1,2,6,8])
#
l1 = {1,2,6,8}
l2 = {2,3,5,8}
l3 = l1 - l2


作为一种替代方法,您也可以将filter与lambda表达式一起使用,以获得所需的结果。例如:

1
2
3
4
5
6
7
>>> l1 = [1,2,6,8]
>>> l2 = set([2,3,5,8])

#     v  `filter` returns the a iterator object. Here I'm type-casting
#     v  it to `list` in order to display the resultant value
>>> list(filter(lambda x: x not in l2, l1))
[1, 6]

性能比较

这里我比较一下这里提到的所有答案的性能。正如预期的那样,Arkku基于set的运营速度最快。

  • Arkku的设置差异-第一个(每个循环0.124 usec)

    1
    2
    mquadri$ python -m timeit -s"l1 = set([1,2,6,8]); l2 = set([2,3,5,8]);""l1 - l2"
    10000000 loops, best of 3: 0.124 usec per loop
  • Daniel Pryden对set查找的列表理解-秒(每个循环0.302 usec)

    1
    2
    mquadri$ python -m timeit -s"l1 = [1,2,6,8]; l2 = set([2,3,5,8]);""[x for x in l1 if x not in l2]"
    1000000 loops, best of 3: 0.302 usec per loop
  • 甜甜圈的清单理解在普通清单-第三个(0.552个使用循环)

    1
    2
    mquadri$ python -m timeit -s"l1 = [1,2,6,8]; l2 = [2,3,5,8];""[x for x in l1 if x not in l2]"
    1000000 loops, best of 3: 0.552 usec per loop
  • Moinuddin Quadri使用filter四分之一(每个循环0.972 usec)

    1
    2
    mquadri$ python -m timeit -s"l1 = [1,2,6,8]; l2 = set([2,3,5,8]);""filter(lambda x: x not in l2, l1)"
    1000000 loops, best of 3: 0.972 usec per loop
  • Akshay Hazari使用reducefilter-第五个(每个回路3.97 usec)

    1
    2
    mquadri$ python -m timeit"l1 = [1,2,6,8]; l2 = [2,3,5,8];""reduce(lambda x,y : filter(lambda z: z!=y,x) ,l1,l2)"
    100000 loops, best of 3: 3.97 usec per loop

ps:set不维护顺序,从列表中删除重复元素。因此,如果您需要其中任何一个,请不要使用设置差异。


替代解决方案:

1
reduce(lambda x,y : filter(lambda z: z!=y,x) ,[2,3,5,8],[1,2,6,8])