Функции фильтрации из модуля itertools

Курс по стандартной библиотеке: https://stepik.org/a/259466?utm_source=proproprogs

Смотреть материал на YouTube | RuTube

Следующая функция filterfalse() модуля itertools работает по аналогии с функцией filter(), которую мы рассматривали в базовом курсе языка Python. Разница лишь в том, что filterfalse() возвращает элементы итерируемой последовательности, для которых функция условия возвращает False. Например, пусть имеется последовательность чисел:

digits = [1, 2, 3, 4]

Тогда, применяя к ней функцию filterfalse(), получим:

res_it = filterfalse(lambda x: x % 2 == 0, digits)
res = list(res_it) # [1, 3]

Лямбда-функция возвращает False для нечетных значений, именно они и выделяются, как результат работы.

Или другой пример. Допустим, что в следующем списке:

text = ["Hello", "", " ", None, "Python"]

нужно убрать все пустые строки, включая пробельные символы и значения None. С помощью filterfalse() это можно сделать следующим образом:

res_it = filterfalse(lambda x: True if x is None else not bool(x.strip()), text)

Как видите, здесь мы имеем более сложное условие. Но принцип везде один: если для текущего значения x функция условия возвращает False, то элемент остается, иначе отбрасывается.

Функция dropwhile()

Следующая функция dropwhile() пропускает элементы итерируемого объекта до тех пор, пока заданная предикатная функция (функция условия) возвращает значение True, а затем возвращает все оставшиеся элементы.

Например, для списка:

digits = [1, 2, -3, 4, 5, 6, -7, -8]

следующий вызов функции dropwhile() вернет все значения, начиная с первого отрицательного:

res_it = dropwhile(lambda x: x > 0, digits)
res = list(res_it)  # [-3, 4, 5, 6, -7, -8]

Почему мы получили такой результат? Очевидно, что для первых двух значений 1 и 2 списка digits лямбда-функция возвращает True, следовательно, они пропускаются. А для третьего значения -3 имеем False, поэтому все элементы с 3-го и до последнего будут возвращаться итератором res_it.

Функцию dropwhile() удобно использовать для упорядоченных, отсортированных последовательностей. В частности, если значения отсортированы по возрастанию:

numbers = range(-10, 10, 2) # [-10, -8, -6, -4, -2, 0, 2, 4, 6, 8]

то dropwhile() позволяет легко разбить ее на две части по заданному критерию. Например, пропустить отрицательные и оставить положительные:

res_it = dropwhile(lambda x: x <= 0, numbers)  # [2, 4, 6, 8]

Функция takewhile()

Противоположная функция takewhile() наоборот оставляет элементы итерируемого объекта, пока функция условия возвращает True. Например:

res_it = takewhile(lambda x: x <= 0, numbers) # [-10, -8, -6, -4, -2, 0]
res_it = takewhile(lambda x: x > 0, digits) # [1, 2]

Функция compress()

Последняя функция compress(), которую мы рассмотрим на этом занятии, позволяет отбирать элементы коллекции на основе значений второй коллекции:

itertools.compress(data, selectors)

  • data – обрабатываемая коллекция данных;
  • selectors – коллекция, определяющая, какие элементы оставить, а какие исключить.

Пусть, например, у нас имеется список data с данными и кортеж selector с селекторами:

data = ["яблоко", "груша", "банан", "виноград", "персик"]
selector = (True, False, True, False, True)

Тогда следующий вызов функции compress():

res_it = compress(data, selector)
res = list(res_it)  # ['яблоко', 'банан', 'персик']

оставит три значения: 'яблоко', 'банан', 'персик', для которых элементы в selector равны True. Остальные будут отброшены.

Этот же самый пример можно записать и в другом виде. В качестве селекторов не обязательно прописывать булевы значения True/False, можно указывать любые другие данные, к которым допустимо применять функцию bool():

selector2 = (1, 0, 100, "", "hello", [])

Обратите внимание, что длина кортежа selector2 на один больше списка data. Давайте посмотрим, как отработает следующий вызов функции compress():

res_it = compress(data, selector2)  # ['яблоко', 'банан', 'персик']

Увидим тот же результат из трех элементов. То есть, длины передаваемых коллекций могут различаться и тогда итерирование идет по самой короткой из них. В частности:

res_it = compress(data, selector2[:4])  # ['яблоко', 'банан']

Также в качестве селектора можно объявить, например, выражение-генератор:

selector3 = (len(x) < 7 for x in data)

и указать его вторым аргументом:

res_it = compress(data, selector3) # ['яблоко', 'груша', 'банан', 'персик']

На выходе получим четыре строки, длины которых меньше семи.

Вот основные функции фильтрации элементов коллекций модуля itertools.

Курс по стандартной библиотеке: https://stepik.org/a/259466?utm_source=proproprogs

Видео по теме