[英]python delete all entries of a value in list
為什么此for循環不起作用? 我的目標是從列表中刪除每1
。
>>> s=[1,4,1,4,1,4,1,1,0,1]
>>> for i in s:
... if i ==1: s.remove(i)
...
>>> s
[4, 4, 4, 0, 1]
在迭代列表時,切勿更改列表。 正如您在此處看到的那樣,結果是不可預測的。 一個簡單的替代方法是構造一個新列表:
s = [i for i in s if i != 1]
如果出於某種原因您必須絕對地編輯列表而不是構造一個新列表,那么最好的答案是遍歷該列表以找到必須刪除的索引,然后反向遍歷該索引列表以將其刪除一個:
indices_to_remove = [i for (i, val) in enumerate(s) if val == 1]
for i in reversed(indices_to_remove):
del s[i]
因為這樣會首先從列表末尾刪除元素,所以計算出的原始索引仍然有效。 但是,除非有特殊情況,否則我通常希望計算新列表。
考慮以下代碼:
#!/usr/bin/env python
s=[1, 4, 1, 4, 1, 4, 1, 1, 0, 1]
list_size=len(s)
i=0
while i!=list_size:
if s[i]==1:
del s[i]
list_size=len(s)
else:
i=i + 1
print s
結果:
[4, 4, 4, 0]
簡而言之,由於每次切斷數字1
都會更改列表的“大小”和“索引位置”,因此代碼會得到一些不良結果,並且代碼已被證明for each loop
Python
for each loop
都無法處理帶有動態尺寸。
這是行不通的,因為您要在迭代列表時對其進行修改,並且當前指針會移至要檢查的1
之一之后。 我們可以舉例說明:
>>> for i in s:
... print(s)
... if i == 1:
... s.remove(i)
...
[1_, 4, 1, 4, 1, 4, 1, 1, 0, 1]
[4, 1_, 4, 1, 4, 1, 1, 0, 1]
[4, 4, 1_, 4, 1, 1, 0, 1]
[4, 4, 4, 1_, 1, 0, 1]
[4, 4, 4, 1, 0_, 1]
[4, 4, 4, 1, 0, 1_]
我在要比較的元素上添加了_
。 請注意,總共總共只有6個傳球,而實際上只有1個傳球中的1
被跳過了。 最終導致被刪除的元素是因為list.remove
刪除了指定元素的第一次出現,並且它本身就是一個O(n)操作,一旦列表變大,它就會變得非常昂貴-這就是O(n)即使該項目位於開頭,因為它必須從該項目之后的所有內容中復制所有單個項目,因為python list
相比Java鏈表更像C樣式的數組(如果要使用鏈表,使用collections.deque
)。 O(n)接近結尾,因為它也必須遍歷整個列表以進行自己的比較。 如果使用remove
結果代碼將導致最壞的運行時復雜度O(n log n)。
Peter的答案已經涵蓋了新列表的生成,我只是在回答為什么以及您的原始代碼無法正常工作的原因。
遍歷列表時,請勿更改列表的內容
但是您可以遍歷列表內容的副本並根據情況進行更改
碼:
s=[1,4,1,4,1,4,1,1,0,1]
for i in s[:]:
if i ==1: s.remove(i)
print s
輸出:
[4, 4, 4, 0]
如@metatoaster所述,您可以使用filter
碼:
s=[1,4,1,4,1,4,1,1,0,1]
s=list(filter(lambda x:x !=1,s))
print s
[4, 4, 4, 0]
您可以使用過濾器刪除多個示例
碼:
s=[1,4,1,4,1,4,1,1,0,1,2,3,5,6,7,8,9,10,20]
remove_element=[1,2,3,5,6,7,8,9]
s=list(filter(lambda x:x not in remove_element,s))
print s
[4, 4, 4, 0, 10, 20]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.