Delete instance from list?


7 posts
by davef21370 » Tue Feb 05, 2013 2:01 pm
I have a list of classes to do some simple scoring animation in a game. When the player picks up a bonus I append a new instance of my animation class to the list, while the animation is running the function returns True, when it has finished it returns False, at this point I need to delete the instance and remove it from the list.

At the moment I have...(excuse the indentation, it's fine in the code, b****y iPad)
Code: Select all
for a in ascore:
if a.anim == False:
a = None

But after quitting the program and typing 'print ascore' I still get a list of references to all the instances created.
I also had...
Code: Select all
a.remove()

to remove the instance from the list but that threw a spanner in the works, something to do with doing it while still looping through the list.

Basically, how do I remove an item from a list while still being able to loop through the list and how do I delete an instance of a class?

Thanks in advance.
Dave.
Please feel free to tap into my abundant lack of knowledge.
When you're dead you don't know you're dead. It's the same as being stupid.
Apple say. Monkey do.
User avatar
Posts: 735
Joined: Fri Sep 21, 2012 4:13 pm
Location: Up North
by alexeames » Tue Feb 05, 2013 2:33 pm
Would it be any use to copy the list and iterate through the copy, whilst performing changes on the original?

(I'm sure you know this, but...)
Code: Select all
newlist = oldlist[:]
Alex Eames RasPi.TV, RasP.iO
User avatar
Forum Moderator
Forum Moderator
Posts: 2777
Joined: Sat Mar 03, 2012 11:57 am
Location: UK
by davef21370 » Tue Feb 05, 2013 3:14 pm
I hadn't actually thought of that, cheers.
I may iterate through the list and build a new list using only the instances that return True then copy the new list back to the original.
There must be a more elegant solution but that'll work for now.

Thanks.
Please feel free to tap into my abundant lack of knowledge.
When you're dead you don't know you're dead. It's the same as being stupid.
Apple say. Monkey do.
User avatar
Posts: 735
Joined: Fri Sep 21, 2012 4:13 pm
Location: Up North
by Sleep Mode zZ » Tue Feb 05, 2013 4:25 pm
When I make a google search to find a solution to a prgramming problem, most often the solution is on a page on stackoverflow.com. To this particular problem a more elegant solution might be found on this page: http://stackoverflow.com/questions/1207406/remove-items-from-a-list-while-iterating-in-python.
Posts: 319
Joined: Sun Aug 19, 2012 5:56 am
Location: Finland
by rurwin » Tue Feb 05, 2013 4:34 pm
Code: Select all
ascore = filter(lambda a: a.anim, ascore)


filter(x, y) returns a list consisting of those members of list y for which the function x returns True.

The function you want would be:
Code: Select all
def f(a):
    a.anim == True

But since you only want it once, you don't have to make it a separate definition; that's what lambdas are for. And you should never compare with True, that is redundant and inefficient. So function x is just "lambda a: a.anim"

You pass in list ascore, and filter returns a new list ascore with only those members for which the anim attribute is True.

Edit: and in line with that StackOverflow code, it may or may not be more correct to do:
Code: Select all
ascore[:] = filter(lambda a: a.anim, ascore)

depending on how you expect references to work:

Code: Select all
x = ascore
ascore = filter(lambda a: a.anim, ascore)

# x and ascore are now different lists.

or
Code: Select all
x = ascore
ascore[:] = filter(lambda a: a.anim, ascore)

# both x and ascore are now the new list
User avatar
Forum Moderator
Forum Moderator
Posts: 4106
Joined: Mon Jan 09, 2012 3:16 pm
by timhoffman » Tue Feb 05, 2013 10:56 pm
Hi

A couple of things, just saying a=None does nothing to the instance it just rebinds the name 'a' to None.
Also the list still holds a reference.

Are you only removing some of the items in the list or everything ?

Normally deleting items from a list whilst iterating over it is probably not a good idea. Maybe consider a different approach.

If you can process the list in reverse order the you could do the following.

Code: Select all
for i in some_list[-1::-1]:
    # do something with i
    some_list.pop()
   
 


This code iterates over the list in reverse order, and pops the last item from the list on each iteration.

May be a dictionary might be a more appropriate container, or if you need order maintained an OrderedDict, which will allow you to remove items by key rather than by index.

T
Posts: 85
Joined: Sat Nov 05, 2011 11:31 pm
by IanH » Wed Feb 06, 2013 8:28 am
If you're finding lambda-expressions are hard to read, you could use a list comprehension, thus:

Code: Select all
alist = [ a for a in alist if a.anim ]


Note you could also write 'if (a.anim==True)', instead of 'if a.anim', but it's not necessary.
https://github.com/IanHarvey
Posts: 67
Joined: Mon Dec 19, 2011 5:53 pm