How to delete list elements while cycling the list itself without duplicate it

廉价感情. 提交于 2019-12-06 15:49:29

Filter (or list comprehension) IS the way to go. If you want to do it inplace, something like this would work:

purge = []
for i,object in enumerate(self.list):
    if object.mycond()
        purge.append(i)
for i in reversed(purge):
    del self.list[i]

Or alternatively, the purge list can be made with a comprehension, a shortcut version looks like:

for i in reversed([ i for (i,o) in enumerate(self.list) if o.mycond() ]):
    del self.list[i]

Don't try. Just don't. Make a copy or generate a new list.

Just make yourself a new list:

def purge(self):
    self.list = [object for object in self.list if not object.my_cond()]
    return self.list

Reserve any optimization until you've profiled and found that this method really is the bottleneck of your application. (I bet it won't be.)

In python variables are actually labels to data. Duplicating a list is, for the most part, making a new set of pointers to the data from the first list. Don't feel too bad about it.

List comprehensions are your friend.

e.g.

>>> a = range(20)
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> [ x for x in a if x % 2 == 0 ]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

Your second solution in which you duplicate the list is the right way to go. Afterward you can just replace the old list with the duplicate if need be.

It's perfectly safe to shorten the list in place if you do it in reverse!

>>> a=range(20)
>>> for i in reversed(range(len(a))):
...     if a[i]%2: del a[i]
... 
>>> a
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

Another way is to reassign the whole slice

>>> a=range(20)
>>> a[:]=(x for x in a if not x%2)
>>> a
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

If the items in the list are unique, this works too

>>> a=range(20)
>>> for item in reversed(a):
...  if item%2: a.remove(item)
... 
>>> a
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

Here is some more explanation in response to yuri's comment

Suppose we have

>>> a=[0,1,2,3,4,5]

Now trying naively to delete the 3rd and 4th items

>>> del a[3]
>>> del a[4]
>>> a
[0, 1, 2, 4] # didn't work because the position of all the item with index >=3 was changed

However if we do the del's in the opposite order

>>> a=[0,1,2,3,4,5]
>>> del a[4]
>>> del a[3]
>>> a
[0, 1, 2, 5] # this is the desired result

Now extend that idea over a for loop with a removal condition, and you see that removal from the live list is possible

indeces = []
minus = 0

for i in range(self.list):
    if cond(self.list[i]):
        indeces.append(i)

for i in indeces:
    self.list = self.list[:(i-minus)].extend(self.list[i-minus+1:])
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!