2

我有一个这样的数组数组

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

5 回答 5

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

你的错误是删除itemdataSet但即使你删除了元素,set你最终会在迭代列表时修改列表,这意味着进一步的迭代将跳过元素:

>>> lst = ['323434', '311472', '311472', '323412', '166282']
>>> for i in lst:
...     if i == '311472':
...         lst.remove(i)
... 
>>> lst
['323434', '311472', '323412', '166282']

这是因为列表迭代器移动到下一个索引,而不管以后从列表中添加或删除;当删除'311472'索引 1 处的第一个时,循环继续移动到列表中的索引 2,其中索引 1 之后的所有内容都向下移动一个位置。

于 2013-10-07T08:56:10.863 回答
4

您从错误的列表中删除。试试set.remove(item)吧。

但请注意,这仅在数据唯一的情况下才有效,即您只有一个匹配条件,因为当您在循环内删除时会跳过索引。

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

于 2013-10-07T08:55:46.557 回答
0

我们必须从列表中删除“311472”

所以尝试从该列表中删除列表 [list.remove] 即,

a=[['387230'], ['296163'], ['323434', '311472', '323412', '166282'], ['410119']]

用于 a 中的 ina: 用于 ina 中的 inaina: 如果 inaina=="311472": ina.remove("311472") 打印 a

于 2013-10-07T09:21:30.437 回答
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:]

没有例外,只有一个通过列表,但一些笨拙的索引计算。不过,这可能与内存效率一样高。

于 2013-10-07T09:18:22.233 回答
0

如果您想就地修改列表,可以使用以下代码(我相信这符合您的原始计划):

for set in dataSet:
    while "311472" in set:
        set.remove("311472")

如果在一个单曲中有很多次重复(顺便说一句。这不是一个好的列表名称,并且隐藏了同名的内置函数),这可能会很慢。"311472"set

于 2013-10-07T09:17:52.623 回答