我不喜欢以下从列表中删除元素的方式:
try:
lst.remove(elt)
except ValueError:
pass
我知道在 Python 中使用 try except block 是可以的,而且我实际上使用了它们,但在这种特殊情况下,我希望在我不使用时有一个 list.remove_if_exists(elt)
方法确实需要处理元素不在列表中的情况。
为了让事情更清楚,我尝试使用列表理解:
lst = [x for x in lst if x != elt]
然而,这会变慢:
In [3]: %timeit [x for x in lst if x != elt]
1000 loops, best of 3: 334 µs per loop
In [4]: %timeit lst[:].remove(elt)
10000 loops, best of 3: 42.8 µs per loop
这是为什么呢?以及如何以一种优雅高效的方式从列表中删除一个项目,无论它是否存在?
编辑:人们提到原因是 list.remove
在找到元素时停止并且列表理解遍历所有元素,因此,它应该更慢。
所以我尝试删除列表中的最后一个元素 elt = lst[-1]
,以便两个进程都到达列表的最后:
In [7]: %timeit [x for x in lst if x != elt]
1000 loops, best of 3: 343 µs per loop
In [8]: %timeit lst[:].remove(elt)
10000 loops, best of 3: 143 µs per loop
为什么 list.remove
仍然比列表理解更快?大约快两倍。
PS:我仍然很乐意就在不关心其实际成员资格的情况下删除列表中的元素的优雅而有效的方法提出建议。
最佳答案
如评论中所述,无论列表的内容是什么,您的列表理解都是 O(n)
,而 remove
将遍历列表直到第一个元素存在,然后将中断。所以这取决于您要删除的元素的位置。
remove
快得多的第二个原因是它是用 C 实现的,解释器有调用魔术方法 __eq__
的开销,而 C 代码调用 C函数(PyObject_RichCompareBool
)。
你可以在这里看到源代码:
https://svn.python.org/projects/python/trunk/Objects/listobject.c
搜索 listremove
关于python - 为什么 list.remove 比列表理解更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43911107/