从一个列表中删除另一个列表中出现的所有元素

2024-03-28 13:01:48 发布

您现在位置:Python中文网/ 问答频道 /正文

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

我可以想出一种简单的循环方法来实现这一点,但这将是非常低效的。什么是一个Python式的有效方法

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


Tags: and方法元素l1列表l2
3条回答

性能比较

比较python3.9.1python2.7.16上这里提到的所有答案的性能

Python 3.9.1

答案按性能顺序列出:

  1. Arkku'sset使用减法进行差分“-”运算-(每个循环91.3纳秒)

    mquadri$ python3 -m timeit -s "l1 = set([1,2,6,8]); l2 = set([2,3,5,8]);" "l1 - l2"
    5000000 loops, best of 5: 91.3 nsec per loop
    
  2. Moinuddin Quadri's使用set().difference()-(每个环路133毫微秒)

    mquadri$ python3 -m timeit -s "l1 = set([1,2,6,8]); l2 = set([2,3,5,8]);" "l1.difference(l2)"
    2000000 loops, best of 5: 133 nsec per loop
    
  3. Moinuddin Quadri's基于set查找的列表理解-(每个循环366nsec)

     mquadri$ python3 -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 5: 366 nsec per loop
    
  4. Donut's普通列表上的列表理解-(每个循环489纳秒)

     mquadri$ python3 -m timeit -s "l1 = [1,2,6,8]; l2 = [2,3,5,8];" "[x for x in l1 if x not in l2]"
     500000 loops, best of 5: 489 nsec per loop
    
  5. Daniel Pryden's生成器表达式,使用基于set的查找并键入强制转换到list-(每个循环583 nsec):按照OP的请求显式键入强制转换到list,以获得最终对象为^{。如果将生成器表达式替换为列表理解,则与相同Moinuddin Quadri's基于set查找的列表理解。

     mquadri$ mquadri$ python3 -m timeit -s "l1 = [1,2,6,8]; l2 = set([2,3,5,8]);" "list(x for x in l1 if x not in l2)"
     500000 loops, best of 5: 583 nsec per loop
    
  6. Moinuddin Quadri's使用filter()并显式键入转换到list(需要显式键入转换,如Python3.x中所示,它返回迭代器)(每个循环681nsec)

     mquadri$ python3 -m timeit -s "l1 = [1,2,6,8]; l2 = set([2,3,5,8]);" "list(filter(lambda x: x not in l2, l1))"
     500000 loops, best of 5: 681 nsec per loop
    
  7. Akshay Hazari's使用functools.reduce+^{>-(每个循环3.36 usec)的组合:从Python 3.x显式键入casting到list,它开始返回迭代器。我们还需要导入functools以在Python 3.x中使用reduce

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

Python 2.7.16

答案按性能顺序列出:

  1. Arkku'sset使用减法进行差分“-”运算-(每个循环0.0783 usec)

    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.0783 usec per loop
    
  2. Moinuddin Quadri's使用set().difference()-(每个循环0.117 usec)

    mquadri$ mquadri$ python -m timeit -s "l1 = set([1,2,6,8]); l2 = set([2,3,5,8]);" "l1.difference(l2)"
    10000000 loops, best of 3: 0.117 usec per loop
    
  3. Moinuddin Quadri's基于set查找的列表理解-(每个循环0.246 usec)

     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.246 usec per loop
    
  4. Donut's普通列表上的列表理解-(每个循环0.372 usec)

     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.372 usec per loop
    
  5. Moinuddin Quadri's使用filter()-(每个循环0.593usec)

     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.593 usec per loop
    
  6. Daniel Pryden's生成器表达式,使用基于set的查找并键入强制转换到list-(每个循环0.964个):按照OP的请求显式键入强制转换到list以获得最终对象^{。如果将生成器表达式替换为列表理解,则它将与{a2}使用基于set的查找进行列表理解。

     mquadri$ python -m timeit -s "l1 = [1,2,6,8]; l2 = set([2,3,5,8]);" "list(x for x in l1 if x not in l2)"
     1000000 loops, best of 3: 0.964 usec per loop
    
  7. Akshay Hazari's使用functools.reduce+filter-(每个循环2.78 usec)

     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: 2.78 usec per loop
    

Python有一个名为List Comprehensions的语言特性,非常适合使这类事情变得非常简单。下面的语句完全按照您的要求执行,并将结果存储在l3

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

l3将包含[1, 6]

一种方法是使用集合:

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

但是,请注意,集合不会保留元素的顺序,并会导致删除任何重复的元素。元素还需要是可散列的。如果这些限制是可以容忍的,那么这通常可能是最简单、性能最高的选项

相关问题 更多 >