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

Какой самый идиоматический способ написания filter с отрицанием?

Пример:

is_even= lambda x : x % 2 == 0
odd_numbers= filter( lambda x: not is_even(x), range(10) )

Конечно, вы можете просто использовать понимание списка, но тогда вам все равно не нужно использовать filter

Если кому-то интересно, я наткнулся на это, пытаясь разбить список на основе условия


person loopbackbee    schedule 09.01.2015    source источник
comment
Если кому-то интересно, я пытаюсь разбить список на основе условие   -  person loopbackbee    schedule 09.01.2015
comment
Это промах ) опечатка?   -  person Bhargav Rao    schedule 09.01.2015
comment
Черт, ты отредактировал это через 1 секунду после того, как я написал. Это слишком быстро :P..   -  person Bhargav Rao    schedule 09.01.2015
comment
Можете ли вы рассказать нам, что вы на самом деле пытаетесь сделать? Пожалуйста, более широкое описание. Что не так с тем, что вы опубликовали?   -  person Reut Sharabani    schedule 09.01.2015
comment
@ReutSharabani Я упоминал об этом в комментариях, но я перенесу это к самому вопросу. Нет ничего неправильного в том, что я написал, мне просто интересно, есть ли более идиоматический или менее подробный способ сделать это   -  person loopbackbee    schedule 09.01.2015
comment
Нет необходимости писать две лямбда-функции. Как насчет odd = filter(lambda x: x % 2, range(10))?   -  person Hans Then    schedule 09.01.2015
comment
В модуле itertools есть ifilterfalse(), который фильтрует элементы где функция возвращает False. (itertools.filterfalse() в Python 3). Нет встроенного эквивалента, но not кажется достаточно простым.   -  person Lack    schedule 09.01.2015
comment
@HansThen Для примера предположим, что is_even уже определено   -  person loopbackbee    schedule 09.01.2015
comment
@Lack ifilterfalse кажется именно тем, что я искал, и существует для python 2. Если вы хотите отправить ответ, я приму его   -  person loopbackbee    schedule 09.01.2015
comment
Отлично. Я попытался прояснить разницу между Python 2 и 3 в ответе. Ваш пример (в вопросе) на самом деле дает разные результаты в 2 и 3.   -  person Lack    schedule 09.01.2015


Ответы (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() является дополнением.

person Lack    schedule 09.01.2015
comment
Кто-нибудь знает, почему авторы выбрали ifilterfalse вместо ireject? - person wpcarro; 25.09.2018

Разделение на основе предиката называется 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))
person Karl Bielefeldt    schedule 09.01.2015
comment
Да, это лучшее решение реальной проблемы, если вы используете обе части списка. - person Lack; 09.01.2015
comment
Это, вероятно, стоит опубликовать в вопросе, на который я ссылался, поскольку никто еще не упомянул об этом. Мой вопрос, в частности, был больше мотивирован любопытством, чем практической необходимостью решить фактическое разбиение (для которого уже есть много ответов) - person loopbackbee; 09.01.2015