Skip to content Skip to sidebar Skip to footer

Python Remove Elements From Nested Lists

I have an array of arrays like this dataSet = [['387230'], ['296163'], ['323434', '311472', '323412', '166282'], ['410119']] I would like to delete element '311472' but do not kno

Solution 1:

Use a nested list comprehension, retaining elements instead:

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

Demo:

>>> [[i for i in nested if i != '311472'] for nested in dataSet]
[['387230'], ['296163'], ['323434', '323412', '166282'], ['410119']]

Your mistake was to remove item from dataSet instead, but even if you removed the elements from set you'd end up with modifying the list in place while iterating over it, which means that further iteration will skip elements:

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

That's because the list iterator moves to the next index regardless of later additions or deletions from the list; when removing the first '311472' at index 1 the loop moves on to index 2 in a list where everything past index 1 has moved down a spot.

Solution 2:

You remove from the wrong list. Try set.remove(item) instead.

Beware though, that this only works if the data is unique, i.e. you only have a single match for the condition, because you skip an index when you remove inside the loop.

Martijn provides a complete and pythonic solution.

Solution 3:

If you want to modify the lists in-place, you can use the following code (which I believe is along your original plan):

forsetin dataSet:
    while"311472"inset:
        set.remove("311472")

If there are many many repetitions of "311472" in a single set (btw. not a good name for list, and hides the builtin of the same name), this might be slow.

Solution 4:

we have to remove '311472' from a list

so Try to remove list from that list [list.remove] ie,

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

for ina in a: for inaina in ina: if inaina=="311472": ina.remove("311472") print a

Solution 5:

We're talking about removing every occurence of a given value. list.remove already does a scan, so we can call it before even knowing if it can succeed:

for sublist in dataSet:
    whileTrue:  # list.remove only removes the first occurencetry:
            sublist.remove("311472")
        except ValueError, e:
            break# stop removing, there's no such item in this sublist

This is naturally not very efficient if the list that does contain the removed value is large, because we repeated the removal. For the list comprehension solution Martijn Pieters suggested, the bottleneck is instead if the lists that don't contain the removed value are large (since they are rebuilt).

A third solution is to scan the list and move entries, saving the deallocation of entries to the end:

defremoveAll(lst, item):
    "Like list.remove(), but removes all matching items, without raising ValueError"
    outend=0
    instart=0whileTrue:
        try:
            inend=lst.index(item, instart)
        except ValueError, e:
            # We've reached the end of the listif 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 onesif size and outend!=instart:
            lst[outend:outend+size]=lst[instart:inend]
        outend+=size
        instart=inend+1# Skip over the matching entry

Pretty horrible example of premature optimization - this takes way too long to write and debug, and has only marginal gains compared to the plain rebuilding (likely none at all, depending on the rest of the program). Actually, come to think of it, I don't think there's any gain because the list slicing itself creates subcopies of the parts we want to keep. I suppose it'll do it you have a high rate of the element you want to remove, a very long list, and really want the changes done in-place. Altering the original list after the rebuild solution is trivial:

lst[:]=[item for item in lst if item!=key]

Actually, this just bugged me enough to write another in-place removal variant. This is a somewhat more Pythonic, but still wasteful variant:

defremoveAll2(lst, remove):
    rem=0for idx,value inenumerate(lst):
        if value==remove:
            rem+=1elif rem:
            lst[idx-rem]=value
    if rem:
        del lst[-rem:]

No exceptions, only one pass over the list, but some clumsy index calculations. This is likely as memory efficient as it gets, though.

Post a Comment for "Python Remove Elements From Nested Lists"