简体   繁体   中英

Python wont remove items from list

filtered_list = ['PerezHilton', 'tomCruise', 'q', 'p']
#BIO[user]['follows'] is just a list of strings say ['a', 'b', 'katieh']
#specs is also a string say eg. 'katieh'
for user in filtered_list:
    if specs not in BIO[user]['follows']:
        filtered_list.remove(user)

The above code for some reson gives this error "ValueError: list.remove(x): x not in list" but clearly 'p' is in the list so why is it not detecting 'p' but it is finding 'q'??

Im soo stumped but any help is appreciated, thanks

** SORRY i FIXED IT NOW *

The list comprehension that does this correctly in one line is at the bottom of the post. Here's some insight into the problem first.

Don't do things like:

for item in list_:
    list_.remove(item)

because bad and confusing things happen.

>>> list_ = range(10)
>>> for item in list_:
...     list_.remove(item)
... 
>>> list_
[1, 3, 5, 7, 9]

Every time you remove an item, you change the indexes for the rest of the items which messes up the loop. One good way to remove items from a list while you're traversing it is to do it by index and work backwards so that removals don't affect the rest of the iterations. This is better because if you remove the 9'th element, then the 8'th element is still the 8'th element but the 10'th element becomes the 9'th element. If you've already dealt with that element, then you don't care what its index is.

>>> list_ = range(10)
>>> for i in xrange(len(list_) - 1, -1, -1):
...     del list_[i]
... 
>>> list_
[]

Or with a while loop:

i = len(list_)
while i:
    i -= 1
    del list_[i]

So in your case, the code would look something like

users[:] = [user for user in users if specs in BIO[user]['follows']]

because this is a filtering job and those are best done with list comprehensions. The point of the [:] is that it assigns to a slice of the list instead of clobbering the reference to the list. This means that every other reference to the list will be updated. It's essentially in-place, except that a copy is made before overwriting the original list. For the sake of completeness, here's how to do it with a while loop.

i = len(users)
while i:
    i -= 1
    if specs not in BIO[users[i]]['follows']:
        del users[i]

You could do this if you wanted it done in place. No copy of the list is made here.

Why are you iterating?

>>> un = ['PerezHilton', 'tomCruise', 'q', 'p']
>>> un.remove('p')
>>> un
['PerezHilton', 'tomCruise', 'q']

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM