Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python throws ValueError: list.remove(x): x not in list

Tags:

Every time I run this program, I get this error:

ValueError: list.remove(x): x not in list 

I am trying to lower the health of a single alien whenever it is hit by a bolt. That single alien should also be destroyed if its health is <= 0. Similarly, the bolt would also be destroyed. Here is my code:

def manage_collide(bolts, aliens):     # Check if a bolt collides with any alien(s)     for b in bolts:         for a in aliens:             if b['rect'].colliderect(a['rect']):                 for a in aliens:                     a['health'] -= 1                     bolts.remove(b)                     if a['health'] == 0:                         aliens.remove(a)     # Return bolts, aliens dictionaries     return bolts, aliens 

The ValueError happens on the line aliens.remove(a). Just to clarify, both the aliens and bolts are lists of dictionaries.

What am I doing wrong?

like image 446
Remolten Avatar asked Jan 02 '13 17:01

Remolten


People also ask

How do I get rid of ValueError in Python?

You must use the remove() method to remove an item that does not exist in order for this error message to appear. To solve the error, you should first check that the item that you want to remove exists in the list. If you want to learn more about coding in Python, check out our How to Learn Python guide.

How do you remove all X from a list in Python?

Use the remove() Function to Remove All the Instances of an Element From a List in Python. The remove() function only removes the first occurrence of the element. If you want to remove all the occurrence of an element using the remove() function, you can use a loop either for loop or while loop.

How do you exclude items from a list in Python?

How to Remove an Element from a List Using the remove() Method in Python. To remove an element from a list using the remove() method, specify the value of that element and pass it as an argument to the method. remove() will search the list to find it and remove it.

Is not in list Python error?

The Python "ValueError: is not in list" occurs when we use the index() method with a value that is not present in the list. To solve the error, check if the value is in the list before using the index method, e.g. if 'value' in my_list: , or use a try/except block.


2 Answers

You should not remove items from a list you are looping over. Create a copy instead:

for a in aliens[:]: 

and

for b in bolts[:]: 

Modifying a list while looping over it, affects the loop:

>>> lst = [1, 2, 3] >>> for i in lst: ...     print i ...     lst.remove(i) ...  1 3 >>> lst [2] 

Removing items from a list you are looping over twice makes things a little more complicated still, resulting in a ValueError:

>>> lst = [1, 2, 3] >>> for i in lst: ...     for a in lst: ...         print i, a, lst ...         lst.remove(i) ...  1 1 [1, 2, 3] 1 3 [2, 3] Traceback (most recent call last):   File "<stdin>", line 4, in <module> ValueError: list.remove(x): x not in list 

When creating a copy of the lists you are modifying at each level of your loops, you avoid the problem:

>>> lst = [1, 2, 3] >>> for i in lst[:]: ...     for i in lst[:]: ...         print i, lst ...         lst.remove(i) ...  1 [1, 2, 3] 2 [2, 3] 3 [3] 

When you have a collision, you only need to remove the b bolt once, not in the loop where you hurt the aliens. Clean out the aliens separately later:

def manage_collide(bolts, aliens):     for b in bolts[:]:         for a in aliens:             if b['rect'].colliderect(a['rect']) and a['health'] > 0:                 bolts.remove(b)                 for a in aliens:                     a['health'] -= 1     for a in aliens[:]:         if a['health'] <= 0:             aliens.remove(a)     return bolts, aliens 
like image 134
Martijn Pieters Avatar answered Nov 03 '22 01:11

Martijn Pieters


There is a bug in your code that is causing this. Your code, simplified, looks like:

for b in bolts:   for a in aliens:     for a in aliens:       bolts.remove(b) 

That is causing you to loop over aliens multiple times for every entry in b. If the b is removed on the first loop over aliens then, when it loops over it a second time, you will get there error.

A few things to fix. First, change in the inner loop over aliens to use something other than a, so:

for b in bolts:   for a in aliens:     for c in aliens:       if hit:         bolts.remove(b) 

Second, only remove b from bolts once. so:

for b in bolts:   for a in aliens:     should_remove = False     for c in aliens:       if hit:         should_remove = True     if should_remove:       bolts.remove(b) 

There are other issues with this code as well, I think, but that is the cause your main problem. Martijn's post may also help.

like image 31
dave mankoff Avatar answered Nov 03 '22 01:11

dave mankoff