Python How to filter object list

eye-catch Python

Python list doesn’t provide a method for filtering. How can we filter the list in Python then?

Sponsored links

filter by for loop

The simplest way is to use for-loop. If the item fulfills the condition, add the item to the result variable.

list_1 = [8, 2, 47, 3, 9, 1, 234, 8, 342, 21]
list_of_list = [[1, 2, 4], [6, 9, 1], [2, 1, 5], [5, 3, 22, 57]]

def filter_with_loop():
    result1 = []
    for item in list_1:
        if item > 10:
            result1.append(item)
    print(result1)

    result2 = []
    for item_list in list_of_list:
        if max(item_list) > 5:
            result2.append(item_list)
    print(result2)


print("--- filter_with_loop ---")
filter_with_loop()
# [47, 234, 342, 21]
# [[6, 9, 1], [5, 3, 22, 57]]
Sponsored links

Using filter class instead

Python list doesn’t offer a filtering method but we can use filter class instead.

filter with lambda

The constructor of filter accepts a function at the first parameter. The second parameter is an iterable object. If the filtering condition is simple enough, using lambda is a good way because it can implement in a short form.

def filter_with_lambda():
    result1 = filter(lambda a: a > 10, list_1)
    # [47, 234, 342, 21]
    print(list(result1))

    result2 = filter(lambda data_list: max(data_list) > 5, list_of_list)
    # [[6, 9, 1], [5, 3, 22, 57]]
    print(list(result2))


print("--- filter_with_lambda ---")
filter_with_lambda()
# [47, 234, 342, 21]
# [[6, 9, 1], [5, 3, 22, 57]]

The results are of course the same as the for-loop version. Don’t forget to cast the result to the desired data type. The result is converted to list here because the result is the instance of filter class.

filter with a function

The code can be multiple lines if the condition is not simple enough. Define a function in this case. Then, pass the function to the filter.

def filter_with_func():
    def bigger_than_10(val):
        return val > 10

    result1 = filter(bigger_than_10, list_1)
    # [47, 234, 342, 21]
    print(list(result1))

    def contains_number_bigger_than_5(data_list):
        return max(data_list) > 5

    result2 = filter(contains_number_bigger_than_5, list_of_list)
    # [[6, 9, 1], [5, 3, 22, 57]]
    print(list(result2))


print("--- filter_without_lambda ---")
filter_with_func()
# [47, 234, 342, 21]
# [[6, 9, 1], [5, 3, 22, 57]]

How to filter a dictionary

The filter class can be used for dictionary too. Let’s check first how dictionary works with for-loop.

data_dict: Dict[str, float] = {
    "aaa": 1.0,
    "bbb": 2.2,
    "ccc": 3.2,
    "ddd": 5.5,
    "eee": 8.0,
}


def show_dict():
    # Consider iterating with .items() pylint(consider-using-dict-items)
    for key in data_dict:
        print(f"{key}, {data_dict[key]}")

    for pair in data_dict.items():
        key, value = pair
        print(f"{pair[0]}, {pair[1]} \t{key}, {value}")


show_dict()
# aaa, 1.0
# bbb, 2.2
# ccc, 3.2
# ddd, 5.5
# eee, 8.0

# aaa, 1.0        aaa, 1.0
# bbb, 2.2        bbb, 2.2
# ccc, 3.2        ccc, 3.2
# ddd, 5.5        ddd, 5.5
# eee, 8.0        eee, 8.0

Pylint shows a warning there if dictionary is used directly to iterate the items. So it’s better to use items() method. pair variable is tuple data type. Therefore, it can be assigned to a key and value in the for-loop.

Let’s pass the items to the second parameter by using items() method.

def dict_filter(pair):
    _key, value = pair
    return value > 3


# {'ccc': 3.2, 'ddd': 5.5, 'eee': 8.0}
print(dict(filter(lambda pair: pair[1] > 3, data_dict.items())))
# {'ccc': 3.2, 'ddd': 5.5, 'eee': 8.0}
print(dict(filter(dict_filter, data_dict.items())))

If no item is found, the result will be empty.

# {}
print(dict(filter(lambda pair: pair[1] > 30, data_dict.items())))

How to filter object list

It’s basically the same way.

class Point:
    def __init__(self, x, y) -> None:
        self.x = x
        self.y = y


points = [
    Point(1, 1),
    Point(2, 2),
    Point(3, 3),
    Point(4, 4),
    Point(5, 5),
]

for point in points:
    print(f"({point.x}, {point.y})")
# (1, 1)
# (2, 2)
# (3, 3)
# (4, 4)
# (5, 5)

If we want to get points where the x is bigger than 3, we can implement it this way.

points = filter(lambda point: point.x > 3, points)

for point in points:
    print(f"({point.x}, {point.y})")
# (4, 4)
# (5, 5)

It overwrites the original value here.

Comments

Copied title and URL