[英]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.