繁体   English   中英

PYTHON从嵌套列表中删除元素

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM