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.
User avatar
Posts: 426
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[:]
My Pi uses 2 watts - what what? ---- HiRes early production Pi photos RS Front Back | Farnell Front Back
User avatar
Posts: 2018
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.
User avatar
Posts: 426
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: 173
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: 2890
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 <-- Pi stuff
Posts: 42
Joined: Mon Dec 19, 2011 5:53 pm