Понятие "фильтрация" интуитивно понятно каждому человеку. Мы пьём фильтрованную воду и фильтруем то, что говорим. В программировании практически то же самое. Операция "фильтрация" по отношению к коллекции означает, что мы отбираем из неё только те элементы, которые удовлетворяют нужному условию. Типичная задача может выглядеть так — выбрать пользователей старше 10 лет:
users = [
{ 'name': 'Igor', 'age': 19 },
{ 'name': 'Danil', 'age': 1 },
{ 'name': 'Vovan', 'age': 4 },
{ 'name': 'Matvey', 'age': 16 },
]
result = []
for user in users:
if user['age'] > 10:
result.append(user)
print(result)
# => [ { 'name': 'Igor', 'age': 19 }, { 'name': 'Matvey', 'age': 16 } ]
Фильтрация встречается так же часто как отображение. Общая схема кода при фильтрации практически один в один как и в отображении, кроме пары ключевых моментов:
- Фильтрация возвращает коллекцию либо того же размера, если ничего не было отфильтровано, либо меньшего. Она может вернуть даже пустую коллекцию, если ни один из элементов не подошёл.
- Фильтрация всегда возвращает исходные элементы. Она никогда не делает отображение. Если на вход фильтрации поступил список пользователей, то список пользователей будет и на выходе.
Теперь посмотрим, как выглядит фильтрация при использовании встроенной функции высшего порядка filter():
filtered_users = filter(lambda user: user['age'] > 10, users)
print(filtered_users) # <filter at 0x71de32b28040>
list(filtered_users) # => [{'name': 'Igor', 'age': 19}, {'name': 'Matvey', 'age': 16}]
Функция, передаваемая в filter()
, должна быть предикатом. То есть её задача вернуть либо True
, либо False
для каждого элемента коллекции. Значение, которое возвращается, никак не используется — оно всего лишь говорит о том, включать ли текущий элемент или нет. Новички часто делают ошибку на этом этапе и начинают возвращать из фильтра то, что они бы хотели увидеть в результате, а для этого надо применять map()
.
На выходе функция возвращает, так же как и map()
, итератор. Получить все элементы из итератора так же можно с помощью list()
Реализация
Напишем свою собственную функцию my_filter()
, работающую аналогично встроенной filter()
:
def my_filter(callback, collection):
for item in collection:
# Предикат используется только для проверки
# Внутрь callback по очереди передается каждый элемент коллекции collection
if callback(item):
# Реализуем ленивость
yield item
users = [
{ 'name': 'Igor', 'age': 19 },
{ 'name': 'Danil', 'age': 1 },
{ 'name': 'Vovan', 'age': 4 },
{ 'name': 'Matvey', 'age': 16 },
]
filtered_users = my_filter(lambda user: user['age'] > 10, users)
list(filtered_users) # [{'name': 'Igor', 'age': 19}, {'name': 'Matvey', 'age': 16}]
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.