Идиоматически отрицать фильтр

Какой самый идиоматичный способ написания 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))
Другие вопросы по тегам