Python List 若將某一筆內容(Value)刪掉,那索引(Index)會自動重新計算,若使用 for + range() 再去 del,會造成一些錯誤。
Python List 刪除內容 會重新 re-index
假設有個 dlist 的 list,裡面塞三筆資料,然後,for 掃一輪遇到內容是 aa 的就移除,會遇到下述問題:
- 在 for + range() 的情況下,dlist 的 index 值遇到刪除就被修改
- for + range() 的 i(index) 值是一開始得到的數字,dlist re-index 後,對 for 的 i 來說並不知道
- 所以就會遇到 key 值找不到的問題
大概範例如下:
# data dlist = [] dlist.append({'id': 'aa'}) dlist.append({'id': 'bb'}) dlist.append({'id': 'cc'}) # 因為我們用 range,list 並不是靠這個 index,所以移除會自動 re-index del_list_index = [] for i in range(len(dlist)): print(dlist) print("0:" + dlist[0]['id']) print("1:" + dlist[1]['id']) print("2:" + dlist[2]['id']) # output # [{'id': 'aa'}, {'id': 'bb'}, {'id': 'cc'}] # 0:aa # 1:bb # 2:cc # List Delete for i in range(len(dlist)): if dlist[i]['id'] == 'aa': print("del id:" + str(i) + dlist[i]['id']) del dlist[i] # 只要一刪除,後面 list 就會自動減少 and re-index print(dlist) print("0:" + dlist[0]['id']) print("1:" + dlist[1]['id']) print("2:" + dlist[2]['id']) # 遇到刪除後,會噴 error
# output for 1 [{'id': 'aa'}, {'id': 'bb'}, {'id': 'cc'}] 0:aa 1:bb 2:cc # output for 2 (del 1 key) [{'id': 'bb'}, {'id': 'cc'}] 0:bb 1:cc Traceback (most recent call last): File "./foreach.py", line 62, in print("2:" + dlist[2]['id']) IndexError: list index out of range
遇到上述的解法有幾種
這篇有提供作法:How do I remove a range (subsection) of a list in Python?
- 下述二選一
- all = all[:max(current - 2, 0)] + all[current:]
- del all[max(current - 2, 0):current]
在這邊來寫第三種作法,直接先把要刪除的 key 存起來,最後掃完一輪後,再對存起來的 keys 掃一輪來刪掉 (不同 List 不會被影響,且需要由大刪到小)
dlist = [] dlist.append({'id': 'aa'}) dlist.append({'id': 'bb'}) dlist.append({'id': 'cc'}) dlist.append({'id': 'dd'}) dlist.append({'id': 'ee'}) del_list_index = [] for i in range(len(dlist)): if dlist[i]['id'] == 'bb' or dlist[i]['id'] == 'dd': print("del id:" + str(i) + dlist[i]['id']) del_list_index.append(i) # 先把要刪除的存著,等等在來刪除 del_list_index.reverse() # 由大排到小,由最大的開始刪除,就不需要擔心 re-index 問題 for index in del_list_index: # 刪除 del dlist[index] print(dlist) # [{'id': 'aa'}, {'id': 'cc'}, {'id': 'ee'}]