I lost a little bit of time in this Python for statement:
class MyListContainer:
def __init__(self):
self.list = []
def purge(self):
for object in self.list:
if (object.my_cond()):
self.list.remove(object)
return self.list
container = MyListContainer()
# now suppose both obj.my_cond() return True
obj1 = MyCustomObject(par)
obj2 = MyCustomObject(other_par)
container.list = [obj1, obj2]
# returning not an empty list but [obj2]
container.purge()
It doesn't work as I expected because when the cycle in "purge" delete the first object in list the second one is shifted to the beginning of the list and the cycle is ended.
I solved duplicating self.list before the for cycle:
...
local_list = self.list[:]
for object in local_list:
...
I suppose that the for statement stop working because I'm changing the length of the original list. Can someone clarify this point ?
And is there a more "elegant" way to solve this problem ? If I have more than few elements inside the list, duplicating it every time does not seem a good idea.
Maybe the filter() function is the right one but i whish to have some other approach if any.
I'm a newbie.
To summarize your useful answers:
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]