Plopperzz
Plopperzz

Reputation: 334

How to remove all of certain data types from list?

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

Answers (6)

Jon Clements
Jon Clements

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

Sudipta
Sudipta

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

flornquake
flornquake

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

Jiri
Jiri

Reputation: 16625

Alternatively, you can use built-in filter function:

filtered_A = filter(lambda i:not(type(i) is str), A)

Upvotes: 9

falsetru
falsetru

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

namit
namit

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

Related Questions