Reputation: 334
I am having some trouble removing only strings from a list of strings and integers. This may seem silly, yet it's true:
>>> A = [1, '2', '3', 4, '5', '4', 6, 56, 7, '4', 6, '543']
>>>
>>> for i in A:
if type(i) is str:
A.remove(i)
>>> A
[1, '3', 4, 6, 56, 7, '4', 6]
Does anybody have any ideas as to what is happening, or if I am simply doing something wrong?
Upvotes: 2
Views: 10397
Reputation: 142256
If your intent is to keep only number-like objects in your list, then that can be made more explicit by using:
A = [1, '2', '3', 4, '5', '4', 6, 56, 7, '4', 6, '543']
from numbers import Number
A[:] = [el for el in A if isinstance(el, Number)]
# [1, 4, 6, 56, 7, 6]
Then, if you wanted to narrow down on specific types of numbers (eg, just ints), you could do:
A = [1, 1.0, 1j]
from numbers import Integral
A[:] = [el for el in A if isinstance(el, Integral)]
# [1]
Upvotes: 0
Reputation: 4971
Never alter(especially add or remove elements) the container you're looping on, because iterators on that container are not going to be informed of your alterations and, as you've noticed, that's quite likely to produce a very different loop and/or an incorrect one.
Like in this case, the first element to be removed from the list is '2'
. In the next iteration, the loop will work for A[2]
, which is now 4
. Hence, the loop never ran for element '3'
.
List comprehensions are best choice for such cases.
Upvotes: 1
Reputation: 3396
Don't remove elements from the list you are looping over, since you won't catch every element:
A = [1, '2', '3', 4, '5', '4', 6, 56, 7, '4', 6, '543']
for i in A:
print(repr(i))
if type(i) is str:
A.remove(i)
# 1, '2', 4, '5', 6, 56, 7, '4', '543'
If you need an explicit loop, copy the list (see the section about for-loop in the tutorial):
for x in A[:]:
if isinstance(x, str):
A.remove(x)
In this case you should use a list comprehension, though.
[x for x in A if isinstance(x, int)]
Upvotes: 0
Reputation: 16625
Alternatively, you can use built-in filter
function:
filtered_A = filter(lambda i:not(type(i) is str), A)
Upvotes: 9
Reputation: 369444
Removing elements while loop over the list does not work.
Use list comprehension instead:
>>> A = [1, '2', '3', 4, '5', '4', 6, 56, 7, '4', 6, '543']
>>> [x for x in A if not isinstance(x, str)]
[1, 4, 6, 56, 7, 6]
Upvotes: 3
Reputation: 6957
In [1]: A = [1, '2', '3', 4, '5', '4', 6, 56, 7, '4', 6, '543']
In [2]: [x for x in A if type(x)!=str]
Out[2]: [1, 4, 6, 56, 7, 6]
Upvotes: 0