在遍歷list的時候,刪除符合條件的數據,結果不符合預期
num_list = [1, 2, 2, 2, 3] print(num_list) for item in num_list: if item == 2: num_list.remove(item) else: print(item) print(num_list)
結果是
[1, 2, 2, 2, 3] 1 [1, 2, 3]
或者有:
num_list = [1, 2, 3, 4, 5] print(num_list) for i in range(len(num_list)): if num_list[i] == 2: num_list.pop(i) else: print(num_list[i]) print(num_list)
結果報錯:
[1, 2, 3, 4, 5] Traceback (most recent call last): 1 4 5 File "tes.py", line 5, in <module> if num_list[i] == 2: IndexError: list index out of range Process finished with exit code 1
原因是,刪除list中的元素后,list的實際長度變小了,但是循環次數沒有減少,依然按照原來list的長度進行遍歷,所以會造成索引溢出。
1.把列表拷貝,然后對原列表進行刪除操作就沒問題了
num_list = [1, 2, 2, 2, 3] print(num_list) for item in num_list[:]: if item == 2: num_list.remove(item) else: print(item) print(num_list)
結果:
[1, 2, 2, 2, 3] 1 3 [1, 3]
num_list[:]是對原始的num_list的一個拷貝,是一個新的list,所以,我們遍歷新的list,而刪除原始的list中的元素,則既不會引起索引溢出,最后又能夠得到想要的最終結果。此方法的缺點可能是,對於過大的list,拷貝后可能很占內存。
2.從后往前遍歷列表,刪除
3.filter函數
例子 list中去空字符(配合lambda表達式):
condition = lambda t: t != "" (判斷符合條件很復雜就不能使用lambda,自己寫方法吧)
filter_list = list(filter(condition, list)
Python的List的底層是實現是一個PyObject*數組。如果每次增加一個元素都擴張內存的話效率太低,在增加元素的時候所以會有預申請內存。同理刪除元素的時候也不是馬上就減小內存空間,他會按照一定的策略減小。而這種減小不太好預測。
再加上刪除后索引如何調整並沒有明確定義。比如一個長度為3的List你刪除了第2個那么第三個下標應該是2還是3,等等可能會引發歧義。如果這個時候內存達到了需要減小的條件,迭代器就不太好判斷新的索引究竟是多少。
所以Python為了通用性和安全性考慮就禁止在遍歷時刪除元素了。