Reputation: 1858
Tried deleting items in a list, no success.
>>> r = [1,2,3,4,5]
>>> for i in r:
if i<3:
del i
>>> print r
[1, 2, 3, 4, 5]
I even tried filtering it,
>>> def f(i):
True if i>2 else False
>>> print list(filter(f,r))
[]
I do not understand why the first one is not working. And I dont understand the result at all, when I use filter(function,iterable)
.
EDIT:
Seeing Paulo's comment below, now I do not understand why this works.
>>> for i in r:
if i<3:
r.remove(i)
>>> print r
[3, 4, 5]
Shouldn't the iterator problem be still there, and shouldn't the code end up removing only the first element (r[0]
)
Upvotes: 2
Views: 356
Reputation: 49846
I do not understand why the first one is not working.
It is not working because the statement del i
undefines the variable i
- that is, it deletes it from the scope (global or local) which contains it.
And I dont understand the result at all, when I use filter(function,iterable)
Your function, f
does not contain a return statement. Accordingly, it always returns None
, which has the boolean equivalent value of False
. Thus, filter
excludes all values.
What you should probably be doing is filtering using a comprehension, and replacing the list, like so:
r = [i for i in r if i >= 3]
Or, if you really do want to delete part of the original list and modify it, use del
on a slice of the list:
del r[:3]
Seeing Paulo's comment below, now I do not understand why [using
remove
] works.
Because remove(r)
searches for the value r
in the list, and deletes the first instance of it. Accordingly, repeated modification of the list does not affect the iteration that happens inside remove
. However, note that it is still susceptible to the same error, if removal of an item leads to an item being skipped in iteration of the list.
Upvotes: 4
Reputation: 1122172
Use a list comprehension instead:
[i for i in r if i >= 3]
and retain instead of delete.
Your filter never returned the test; so you always return None
instead and that's false in a boolean context. The following works just fine:
def f(i):
return i > 2
Your initial attempt failed because del i
unbinds i
, but the list remains unaffected. Only the local name i
is cleared.
If you want to delete an item from a list, you need to delete the index:
del r[0]
deletes the first element from the list.
Even if you did manage to delete indices the loop would have held some suprises:
>>> for i, element in enumerate(r):
... if element < 3:
... del r[i]
...
>>> r
[2, 3, 4, 5]
This version fails because the list iterator used by the for
loop doesn't know you deleted elements from the list; deleting the value at index 0 shifts up the rest of the list, but the loop iterator looks at item 1 regardless:
r = [1, 2, 3, 4, 5]
, iterator index 0 -> element = 1
r = [2, 3, 4, 5]
, iterator index 1 -> element = 3
Upvotes: 10