PYTHON从嵌套列表中删除元素

PYTHON从嵌套列表中删除元素,python,list,Python,List,我有一个这样的数组 dataSet = [['387230'], ['296163'], ['323434', '311472', '323412', '166282'], ['410119']] 我想删除元素“311472”,但不知道如何删除。我试过了 for set in dataSet: for item in set: if item=="311472": dataSet.remove(item) 但这是行不通的 结果应该是: [['3

我有一个这样的数组

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']]

您从错误的列表中删除。尝试设置。删除(项目)

但是要注意,只有当数据是唯一的时,这才有效,也就是说,对于条件只有一个匹配项,因为在循环内部删除时跳过了索引


Martijn提供了一个完整的python解决方案。

使用嵌套列表理解,保留元素:

dataSet = [[i for i in nested if i != '311472'] for nested in dataSet]
演示:

您的错误是从
数据集
中删除了
,但即使您从
集合
中删除了元素,您最终也会在迭代时修改列表,这意味着进一步的迭代将跳过元素:

>>> 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的所有内容都向下移动了一个点。

如果您想修改列表,可以使用以下代码(我相信这是您最初的计划):


如果在一个
集合中有许多重复的
“311472”
(顺便说一句,这不是列表的好名称,并且隐藏了相同名称的内置项),这可能会很慢。

我们讨论的是删除给定值的每一次出现<代码>列表。删除
已执行扫描,因此我们可以在知道是否可以成功之前调用它:

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]
事实上,这让我非常恼火,以至于写了另一个就地删除变体。这是一种更具python风格但仍然浪费的变体:

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']

对于a中的ina: 对于ina中的ina: 如果inaina==“311472”: ina.删除(“311472”)
打印一张

这不起作用;在适当的位置修改序列将导致遗漏元素。这是一个很好的观点。我仍然认为主要的问题是OP试图从错误的列表中删除。当然,但也许他先尝试了,但对于更复杂的示例,这并没有像预期的那样起作用?这将在整个列表中循环数次以扫描元素;对于测试中的
和调用
.remove()
都会导致性能下降。对于列表中的每一个新元素,您都要加倍努力。@MartijnPieters:这有点太过分了<如果不包含
“311472”
,则
中的code>将仅扫描整个列表(
),在这种情况下,甚至不会调用
删除
。我认为元素的数量不存在二次行为。当然,如果列表仅(或主要)由
“311472”
元素组成,则会出现二次行为(但不一定是因为扫描,而是因为复制)。我指出,这将是缓慢的多次重复。(对于OP给出的示例,此解决方案比您的解决方案快得多。)在最坏的情况下,长元素列表的后半部分只包含大量扫描,每次扫描两次。由于
.remove()
已经扫描,至少Yann的解决方案要好一点。:-)如果只有那个条目,那么每次扫描都很便宜,但每次删除都会花费不必要的代价,因为它会不断重新排列列表中的引用。这种情况最有利于重建解决方案。。后半个病例使扫描费用昂贵,因此可能更糟。抱歉读得太草率了。@MartijnPieters:我仍然不确定我的答案遗漏了什么或错了什么。在某些情况下,它可能很慢,就像我写的那样;您认为应该进一步开发吗?您知道
数据集中
'311472'
的数量吗?这不是一个集合。集合定义为集合(迭代器)
lst[:]=[item for item in lst if item!=key]
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:]