我想知道从列表中删除元素的最佳方式/有效方法是什么。
Python提供few functions:
some_list.remove(value)
,但如果找不到值,则会抛出错误。some_list.pop(some_list[index])
,删除列表中给定位置的项目,然后将其返回。del (some_list[index])
,它从给定索引中删除元素,它与pop不同,因为它不返回值。方案:
答案 0 :(得分:12)
我的回答并不完全是您的问题,但在您阅读本文后,我希望您可以根据自己的需要决定选择哪种类型。
Python的列表是variable-length arrays,而不是Lisp样式的链表。该实现使用对其他对象的连续引用数组,并保留指向此数组的指针。
这使得列表的索引成为[i]一项操作,其成本与列表的大小或索引的值无关。
添加或插入项目时,将调整引用数组的大小。 应用了一些算法来提高重复附加项的性能; 当数组必须增长时,会分配一些额外的空间,以便接下来的几次 不要求实际调整大小,即过度分配。 More Information
删除vs Pop与删除:
乍一看,看起来所有人都在做同样的事情。在幕后它的表现不同。
removing :通过从0索引迭代到第一个来从列表中删除元素 找到元素的匹配。如果元素在最后,则花费更多时间进行迭代。
pop :使用索引从列表中删除元素。花更少的时间。
del :是一个python语句,用于从命名空间或项目中删除名称 使用索引从字典或列表中的项目。
REMOVE:
POP:
DEL:
<强>基准强>:
最坏情况:从列表末尾删除。
yopy:-> python -m timeit "x=range(1000)" "x.pop(999)"
100000 loops, best of 3: 10 usec per loop
yopy:-> python -m timeit "x=range(1000)" "x.remove(999)"
10000 loops, best of 3: 31.3 usec per loop
yopy:-> python -m timeit "x=range(1000)" "del x[999]"
100000 loops, best of 3: 9.86 usec per loop
yopy:->
最佳案例:开始列表。
yopy:-> python -m timeit "x=range(1000)" "x.remove(1)"
100000 loops, best of 3: 10.3 usec per loop
yopy:-> python -m timeit "x=range(1000)" "x.pop(1)"
100000 loops, best of 3: 10.4 usec per loop
yopy:-> python -m timeit "x=range(1000)" "del x[1]"
100000 loops, best of 3: 10.4 usec per loop
yopy:->
需要注意的一点:
如果数组在中间增长或缩小
所以,现在我希望你可以根据自己的需要决定选择什么。
答案 1 :(得分:5)
使用过滤器而不是列表理解:
情景1:
filter(lambda item: 1 <= item <= 5, my_list)
情景2:
to_be_removed = {'a', '1', 2}
filter(lambda item: item not in to_be_removed, my_list)
情景3:
filter(lambda item: some_condition(), my_list)
场景4(嵌套过滤列表):
filter(lambda seq: filter(lambda item: some_condition(), seq), my_list)
出于某种原因,它与列表comprhension是一样的,但很明显我们正在过滤事物而不是生成它们。
答案 2 :(得分:4)
情景1:
[item for item in my_list if 1 <= item <=5 ]
情景2:
to_be_removed = {'a', '1', 2}
[item for item in my_list if item not in to_be_removed ]
情景3:
[item for item in my_list if some_condition()]
场景4(嵌套列表理解):
[[item for item in seq if some_condition] for seq in my_list]
请注意,如果您只想删除一个项目,那么list.remove
,list.pop
和del
肯定会非常快,但在迭代列表时使用这些方法可以导致意外输出。
答案 3 :(得分:1)
很好的问题,对于一些建议的方法,James’ answer是唯一一个具有Python 2.x实际性能数据的人。 (关于该问题,另见my comment。)
要完成Python 3.x的图片,这里还有一些测试。由于单个测试可能会修改其列表,因此我们需要 N 列表来修改 N 测试;因此我在运行测试之前创建了一组列表。
# Python 3.6.2 (default, Jul 18 2017, 14:13:41)
>>> import timeit
>>> number = 10000 # Number of tests.
>>> # Generate `number` lists of 1000 integer elements.
>>> setup = """
... lists=[[_ for _ in range(1000)] for _ in range(10000)]
... i = 0
... """
>>>
所有测试,无论是修改列表而不是生成新列表,都迭代这组列表,以确保测试的条件相同。为简单起见,所有测试都从列表中间删除了一个元素。
让我们从问题的示例开始,使用built-in list() functions:
# remove()
>>> stmt = """
... l = lists[i] # Get the current work list.
... l.remove(500) # Remove element.
... i += 1 # On to the next list.
... """
>>> timeit.timeit(stmt, setup=setup, number=number)
0.08474616194143891
# pop()
>>> stmt = "l = lists[i]; l.pop(500); i += 1"
>>> timeit.timeit(stmt, setup=setup, number=number)
0.01088976499158889
# index() and pop()
>>> stmt = "l = lists[i]; l.pop(l.index(500)); i += 1"
>>> timeit.timeit(stmt, setup=setup, number=number)
0.08841867197770625
# del
>>> stmt = "l = lists[i]; del l[500]; i += 1"
>>> timeit.timeit(stmt, setup=setup, number=number)
0.008702976978383958
# index() and del
>>> stmt = "l = lists[i]; del l[l.index(500)]; i += 1"
>>> timeit.timeit(stmt, setup=setup, number=number)
0.08238211390562356
列出Ashwini Chaudhary’s answer中列出的理解:
>>> stmt = "l = lists[i]; [_ for _ in l if _ != 500]; i += 1"
>>> timeit.timeit(stmt, setup=setup, number=number)
0.44951551605481654
使用Loïc Faure-Lacroix’s answer中概述的过滤器()。但请注意,上面的答案中的示例为Python 3.x返回了一个filter
对象,而不是像Python 2.x那样的列表!
# Generate a filter object.
>>> stmt = "l=lists[i]; filter(lambda _: _ != 500, l); i += 1"
>>> timeit.timeit(stmt, setup=setup, number=number)
0.0031418869039043784
# Generate a list from the filter object.
>>> stmt = "l=lists[i]; list(filter(lambda _: _ != 500, l)); i += 1"
>>> timeit.timeit(stmt, setup=setup, number=number)
1.1863253980409354
使用Python的内置函数删除 not 的元素需要额外的测试;列表推导和过滤器解决方案优雅地处理不存在的列表元素。
# Catch a resulting exception.
>>> stmt = """
... l = lists[i]
... try:
... del l[l.index(1234)]
... except ValueError:
... pass
... i += 1
... """
>>> timeit.timeit(stmt, setup=setup, number=number)
0.1451275929575786
# Test if the element exists, then delete.
>>> stmt = """
... l = lists[i]
... if 1234 in l:
... del l[l.index[1234]]
... i += 1
... """
>>> timeit.timeit(stmt, setup=setup, number=number)
0.13344507792498916
我希望我做对了......