Идиоматически отрицать фильтр
Какой самый идиоматичный способ написания filter
с отрицанием?
Пример:
is_even= lambda x : x % 2 == 0
odd_numbers= filter( lambda x: not is_even(x), range(10) )
Конечно, вы можете просто использовать списочные выражения - но тогда вам не нужно использовать filter
тем не мение
В случае, если кто-то задается вопросом, я наткнулся на это, пытаясь разделить список на основе условия
2 ответа
itertools
Модуль включает в себя оба ifilter () и ifilterfalse (), которые фильтруют элементы, где функция возвращает True
а также False
соответственно.
odd_numbers = ifilterfalse(is_even, range(10))
Обратите внимание, что в Python 2 есть разница между filter
а также ifilter
: odd_numbers
здесь будет итератор, тогда как filter () выдаст список (см. itertools.ifilter против фильтра и списков). Если вы действительно хотите создать список, ваш пример с not
кажется нормально, если вы настроены на использование filter
- понимание списка может быть более "идиоматическим" ( фильтрация списка: понимание списка по сравнению с лямбда + фильтр).
В Python 3 filter () создает итератор, а не список, а itertools.filterfalse () является дополнением.
Расщепление на основе предиката называется partition
, Я нашел бы более идиоматичным для реализации partition
как отдельная функция, а не повторять ее внутренности специально для нечетных и четных чисел. Рецепты Itertools Python 3 имеют следующую реализацию:
def partition(pred, iterable):
'Use a predicate to partition entries into false entries and true entries'
# partition(is_odd, range(10)) --> 0 2 4 6 8 and 1 3 5 7 9
t1, t2 = tee(iterable)
return filterfalse(pred, t1), filter(pred, t2)
Оно использует filterfalse
(как описано @Lack) и tee
определено в этом модуле. Итак, ваш код верхнего уровня будет выглядеть так:
odds, evens = partition(is_even, range(10))