Введение
Встроенная функция filter()
Python может использоваться для создания нового итератора из существующего итерируемого объекта (например списка или словаря), который эффективно отфильтрует элементы с помощью предоставленной нами функции. Итерируемый объект — это объект Python, по которому можно выполнить итерацию, то есть он вернет элементы в такой последовательности, которую мы можем использовать в цикле for
.
Базовый синтаксис для функции filter()
:
filter(function, iterable)
Это вернет итерируемый объект фильтра. Мы можем использовать функцию, например list()
, для составления списка всех элементов, возвращенных в объекте фильтра.
Функция filter()
обеспечивает способ фильтрации значений, который зачастую может быть более эффективным, чем генератор списка, особенно когда мы начинаем работу с большими наборами данных. Например, генератор списка составит новый список, что увеличит время этой обработки. Это означает, что после того, как генератор списка закончит выражение, у нас в памяти будет два списка. Однако filter()
сделает простой объект, содержащий ссылку на оригинальный список, предоставляемую функцию и индекс пути в оригинальном списке, что занимает меньший объем памяти.
В этом обучающем модуле мы рассмотрим четыре разных способа использования filter()
: с двумя различными итерируемыми структурами, с функцией lambda
и без определенной функции.
Использование filter()
с функцией
Первый аргумент в filter()
— это функция, которую мы используем для решения о включении или фильтрации каждого элемента. Функция вызывается один раз для каждого элемента в итерируемом объекте, переданном как второй аргумент и каждый раз при возвращении False
значение сбрасывается. Поскольку этот аргумент является функцией, мы можем либо передать обычную функцию, либо использовать функции lambda
, особенно когда выражение является менее сложным.
Ниже приводится синтаксис lambda
с filter()
:
filter(lambda item: item[] expression, iterable)
С помощью списка ниже можно включить функцию lambda
с выражением, по которому мы хотим оценить каждый элемент из списка:
creature_names = ['Sammy', 'Ashley', 'Jo', 'Olly', 'Jackie', 'Charlie']
Чтобы отфильтровать этот список для поиска названий наших аквариумных созданий, начинающихся с гласной, мы можем запустить следующую функцию lambda
:
print(list(filter(lambda x: x[0].lower() in 'aeiou', creature_names)))
Здесь мы заявляем в нашем списке элемент в качестве x
. Затем мы настроим наше выражение для доступа к первому символу каждой строки (или символу «нуль»), то есть x[0]
. Установка нижнего регистра в каждом из названий обеспечит соответствие букв строке в нашем выражении, 'aeiou'
.
Наконец, мы передадим итерируемому объекту creature_names
. Как и в предыдущем разделе, мы применяем list()
к результату, чтобы создать список из возвратов итератора filter()
.
Вывод будет выглядеть следующим образом:
Output
['Ashley', 'Olly']
Этот же результат можно получить с помощью определяемой нами функции:
creature_names = ['Sammy', 'Ashley', 'Jo', 'Olly', 'Jackie', 'Charlie']
def names_vowels(x):
return x[0].lower() in 'aeiou'
filtered_names = filter(names_vowels, creature_names)
print(list(filtered_names))
Наша функция names_vowels
определяет выражение, которое мы будем применять для фильтра creature_names
.
Снова, вывод будет выглядеть следующим образом:
Output
['Ashley', 'Olly']
В целом, функции lambda
достигают того же результата с filter()
, что и при использовании обычной функции. Необходимость определения обычной функции растет по мере увеличения сложности выражений для фильтрации наших данных, что, скорее всего, будет способствовать улучшению читабельности нашего кода.
Использование None
с filter()
Мы можем передать None
в качестве первого аргумента filter()
, чтобы исключить из возвращенного фильтра итератора любые значения, которые Python считает «ложными». Обычно Python считает все значения длиной 0
(например пустой список или пустую строку) или числовой эквивалент 0
ложными, отсюда использование термина «ложный».
В следующем случае мы хотим фильтровать наш список так, чтобы отображались только номера номера емкостей в нашем аквариуме:
aquarium_tanks = [11, False, 18, 21, "", 12, 34, 0, [], {}]
В этом коде у нас есть список, содержащий целые числа, пустые последовательности и логическое значение.
filtered_tanks = filter(None, aquarium_tanks)
Мы используем функцию filter()
с None
и передадим список aquarium_tanks
в качестве нашего итерируемого объекта. Поскольку мы передали None
в качестве первого аргумента, проверим, считаются ли элементы в нашем списке ложными.
print(list(filtered_tanks))
Затем обернем filtered_tanks
в функцию list()
для возврата списка для filtered_tanks
при печати.
Здесь мы видим, что вывод отображает только целые значения. Все элементы, оцененные как False
, равные 0
по длине, были удалены filter()
:
Output
[11, 25, 18, 21, 12, 34]
Примечание. Если мы не используем list()
и печатаем filtered_tanks
, мы получим объект фильтра вроде <filter object at 0x7fafd5903240>
. Объект фильтра является итерируемым, поэтому мы можем пройтись по нему с помощью for
или использовать list()
для превращения его в список, который мы здесь делаем, так как это хороший способ проверки результатов.
C None
мы использовали filter()
для быстрого удаления элементов из нашего списка, которые считались ложными.
Использование filter()
со списком словарей
Когда у нас имеется более сложная структура данных, мы все еще можем использовать filter()
для оценки каждого из элементов. Например, если у нас есть список словарей, мы не только хотим выполнить итерацию по каждому элементу в списке — одному из словарей, — но мы также хотим выполнить итерацию по каждой паре key:value в словаре, чтобы оценить все данные.
Например, допустим, у нас есть список всех созданий в аквариуме с различными данными о каждом из них:
aquarium_creatures = [
{"name": "sammy", "species": "shark", "tank number": "11", "type": "fish"},
{"name": "ashley", "species": "crab", "tank number": "25", "type": "shellfish"},
{"name": "jo", "species": "guppy", "tank number": "18", "type": "fish"},
{"name": "jackie", "species": "lobster", "tank number": "21", "type": "shellfish"},
{"name": "charlie", "species": "clownfish", "tank number": "12", "type": "fish"},
{"name": "olly", "species": "green turtle", "tank number": "34", "type": "turtle"}
]
Мы хотим фильтровать эти данные по строке поиска, которую мы предоставили функции. Для доступа filter()
к каждому словарю и каждому элементу в словарях, мы создадим вложенную функцию, например:
def filter_set(aquarium_creatures, search_string):
def iterator_func(x):
for v in x.values():
if search_string in v:
return True
return False
return filter(iterator_func, aquarium_creatures)
Мы определяем функцию filter_set()
, которая принимает aquarium_creatures
и search_string
в качестве параметров. В filter_set()
мы передадим iterator_func()
в качестве функции filter()
. Функция filter_set()
вернет итератор, полученный от filter()
.
iterator_func()
принимает x
в качестве аргумента, представляющего элемент в нашем списке (т.е. единый словарь).
Затем цикл for
получит доступ к каждой паре key:value в наших словарях, а затем будет использовать условное выражение для проверки того, есть ли search_string
в v
, представляя значение.
Как и в предыдущих примерах, если выражение оценивает значение как True
, функция добавляет элемент в объект фильтра. Оно вернется после выполнения функции filter_set()
. Мы расположим return False
за пределами нашего цикла для проверки каждого элемента в каждом словаре вместо получения результатов после проверки одного первого словаря.
Мы вызовем filter_set()
с нашим списком словарей и строкой поиска, для которых мы хотим найти совпадения:
filtered_records = filter_set(aquarium_creatures, "2")
После выполнения функции мы сохраним объект фильтра в переменной filtered_records
, которую мы превращаем в список и печатаем:
print(list(filtered_records))
Мы увидим следующий вывод из этой программы:
Output
[{'name': 'ashley', 'species': 'crab', 'tank number': '25', 'type': 'shellfish'}, {'name': 'jackie', 'species': 'lobster', 'tank number': '21', 'type': 'shellfish'}, {'name': 'charlie', 'species': 'clownfish', 'tank number': '12', 'type': 'fish'}]
Мы отфильтровали список словарей по строке поиска 2
. Мы видим, что вернулись три словаря, включающие номер емкости с 2
. Использование нашей собственной вложенной функции позволило нам получить доступ к каждому элементу выполнить эффективную проверку относительно каждой строки поиска.
Заключение
В этом обучающем модуле мы узнали о различных способах использования функции filter()
в Python. Теперь вы можете использовать filter()
со своей собственной функцией, функцией lambda
или с None
для фильтрации элементов структур данных различной сложности.
Хотя в этом обучающем модуле мы сразу же печатали результаты из filter()
в формате списка, в наших программах мы, скорее всего, будем использовать возвращенный объект filter()
и выполнять дальнейшие манипуляции с данными.
Для получения дополнительной информации о Python ознакомьтесь с нашей серией Программирование на Python 3 и посетите нашу тематическую страницу, посвященную Python.