簡體   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