How to select elements of a specific type in a list?

Question:

I am trying to write a function to select only the elements of my_list that are of the type specified by type_elem. Here is my code:

def filter_list(my_list, type_elem):
    for elem in my_list:
        if type_elem == int and isinstance(elem, str):
            my_list.remove(elem)
    return my_list


print(filter_list([35, True, 'abc', 10], int))

In this case output must be: [35, 10]
If it were str, for example, as a second argument, the output must be ['abc']. And so on

Asked By: Dima

||

Answers:

In your situation, you don’t actually care what type_elem is: you only care about whether an element of the list is an instance of type_elem. This can be checked by simply doing if isinstance(elem, type_elem).

Also, you should create a new list to which you add the elements you want, instead of removing from the one you are iterating over, since that can lead to problems.

Your function would become:

def filter_list(my_list, type_elem):
    result = []
    for elem in my_list:
        if isinstance(elem, type_elem):
            result.append(elem)

    return result

Since you’re just building up the result list in that loop, it can be replaced by a list comprehension:

def filter_list(my_list, type_elem):
    return [elem for elem in my_list if isinstance(elem, type_elem)]

Now, calling the function with different type_elem returns a list containing only the elements of that type:

>>> print(filter_list([35, True, 'abc', 10], int))
[35, True, 10]

>>> print(filter_list([35, True, 'abc', 10], str))
['abc']

>>> print(filter_list([35, True, 'abc', 10], bool))
[True]

Note that the boolean is returned when you ask for ints because a boolean is a special case of integers. To prevent this, we could change the isinstance(elem, type_elem) to type(elem) == type_elem, which checks that the types are equal and doesn’t evaluate to True for derived classes (See https://stackoverflow.com/a/1549854/843953):

def filter_list(my_list, type_elem):
    return [elem for elem in my_list if type(elem) == type_elem]

Now, we get the expected output:

>>> print(filter_list([35, True, 'abc', 10], int))
[35, 10]

>>> print(filter_list([35, True, 'abc', 10], str))
['abc']

>>> print(filter_list([35, True, 'abc', 10], bool))
[True]
Answered By: Pranav Hosangadi

Here the problem is you only remove elements if type_elem == int, so it will work for int but not for other types. Try this:

def filter_list(my_list, type_elem): 
    return [e for e in my_list if isinstance(e, type_elem)]

Take into account that bool type is also an integer type

Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.