[英]PYTHON remove elements from nested lists
我有一個像這樣的數組
dataSet = [['387230'], ['296163'], ['323434', '311472', '323412', '166282'], ['410119']]
我想刪除元素'311472',但不知道如何。 我努力了
for set in dataSet:
for item in set:
if item=="311472":
dataSet.remove(item)
但這不起作用
結果應該是:
[['387230'], ['296163'], ['323434', '323412', '166282'], ['410119']]
使用嵌套列表推導, 保留元素:
dataSet = [[i for i in nested if i != '311472'] for nested in dataSet]
演示:
>>> [[i for i in nested if i != '311472'] for nested in dataSet]
[['387230'], ['296163'], ['323434', '323412', '166282'], ['410119']]
您的錯誤是從dataSet
刪除item
,但即使您從set
刪除了元素,您最終也會在迭代時修改列表,這意味着進一步的迭代將跳過元素:
>>> lst = ['323434', '311472', '311472', '323412', '166282']
>>> for i in lst:
... if i == '311472':
... lst.remove(i)
...
>>> lst
['323434', '311472', '323412', '166282']
這是因為列表迭代器移動到下一個索引,而不管以后添加或刪除列表; 去除所述第一時'311472'
,在索引1處的環在所有過去的索引1已經向下移動的點的列表移動到索引2。
您從錯誤的列表中刪除。 請嘗試使用set.remove(item)
。
但要注意,這僅在數據是唯一的情況下才有效,即您只對條件有一個匹配,因為當您在循環內部刪除時跳過索引。
Martijn提供完整的pythonic解決方案。
如果要在適當位置修改列表,可以使用以下代碼(我認為這與原始計划一致):
for set in dataSet:
while "311472" in set:
set.remove("311472")
如果在一個set
中有許多重復的"311472"
(順便說一句,不是列表的好名稱,並且隱藏了同名的內置),這可能會很慢。
我們正在談論刪除給定值的每個出現。 list.remove
已經進行了掃描,因此我們可以在知道它是否成功之前調用它:
for sublist in dataSet:
while True: # list.remove only removes the first occurence
try:
sublist.remove("311472")
except ValueError, e:
break # stop removing, there's no such item in this sublist
如果包含已刪除值的列表很大,這自然不是非常有效,因為我們重復刪除。 對於列表理解解決方案Martijn Pieters建議,如果不包含刪除值的列表很大(因為它們被重建),瓶頸就是。
第三種解決方案是掃描列表並移動條目,將條目的重新分配保存到最后:
def removeAll(lst, item):
"Like list.remove(), but removes all matching items, without raising ValueError"
outend=0
instart=0
while True:
try:
inend=lst.index(item, instart)
except ValueError, e:
# We've reached the end of the list
if outend!=instart:
# Place remaining items in the correct place and truncate
lst[outend:]=lst[instart:]
return
size=inend-instart
# Move non-matching items down to replace matching ones
if size and outend!=instart:
lst[outend:outend+size]=lst[instart:inend]
outend+=size
instart=inend+1 # Skip over the matching entry
過早優化的相當可怕的例子 - 這需要花費太長時間來編寫和調試,並且與普通重建相比只有微小的收益(可能根本沒有,取決於程序的其余部分)。 實際上,想到它,我認為沒有任何收獲,因為列表切片本身會創建我們想要保留的部分的子索引。 我想它會做你想要刪除的元素的高比率,一個很長的列表,並且真的希望就地完成更改。 在重建解決方案之后更改原始列表是微不足道的:
lst[:]=[item for item in lst if item!=key]
實際上,這只是讓我錯誤地編寫了另一個就地刪除變體。 這是一個更Pythonic,但仍然浪費的變體:
def removeAll2(lst, remove):
rem=0
for idx,value in enumerate(lst):
if value==remove:
rem+=1
elif rem:
lst[idx-rem]=value
if rem:
del lst[-rem:]
沒有例外,只有一個通過列表,但一些笨拙的索引計算。 不過,這很可能是因為內存效率高。
我們必須從列表中刪除“311472”
所以嘗試從該列表中刪除列表[list.remove]即,
a = [['387230'],['296163'],['323434','311472','323412','166282'],['410119']]
in in in:in inaina in ina:if inaina ==“311472”:ina.remove(“311472”)print a
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.