我有一个像这样的数组
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']]
答案 0 :(得分:9)
使用嵌套列表解析,保留元素:
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']]
您的错误是从item
删除dataSet
,但即使您从set
删除了元素,您最终会在迭代时修改列表,这意味着进一步的迭代将跳过元素:
>>> lst = ['323434', '311472', '311472', '323412', '166282']
>>> for i in lst:
... if i == '311472':
... lst.remove(i)
...
>>> lst
['323434', '311472', '323412', '166282']
这是因为列表迭代器移动到下一个索引,而不管以后添加或删除列表;当删除索引1处的第一个'311472'
时,循环移动到列表中的索引2,其中过去索引1的所有内容都向下移动了一个点。
答案 1 :(得分:4)
您从错误的列表中删除。请改为set.remove(item)
。
请注意,这只有在数据是唯一的情况下才有效,即您只有一个条件匹配,因为当您在循环中移除时跳过索引。
Martijn提供完整的pythonic解决方案。
答案 2 :(得分:0)
如果您想要就地修改列表,可以使用以下代码(我认为这与您的原始计划一致):
for set in dataSet:
while "311472" in set:
set.remove("311472")
如果单个"311472"
中有多个多次重复set
(顺便说一句,这不是列表的好名称,并且隐藏了相同名称的内置),这可能会很慢。
答案 3 :(得分:0)
我们正在谈论删除给定值的每个出现。 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:]
没有例外,只有一次通过列表,但有些笨拙的索引计算。不过,这很可能是因为内存效率高。
答案 4 :(得分:0)
我们必须从列表中删除“311472”
所以尝试从该列表中删除列表[list.remove] 即,
a = [['387230'],['296163'],['323434','311472','323412','166282'],['410119']]
for in in: in inaina in ina: 如果inaina ==“311472”: ina.remove( “311472”) 打印