Есть ли функциональная идиома программирования для фильтрации списка по истинам и ложностям? - PullRequest
7 голосов
/ 13 сентября 2010

Скажем, у вас есть список L, и вы хотите разделить его на два списка на основе некоторой логической функции P.То есть вам нужен один список всех элементов l, где P(l) - true, и другой список, где P(l) - false.

. Я могу реализовать это в Python следующим образом:

def multifilter(pred,seq):
    trues,falses = [],[]
    for x in seq:
        if pred(x):
            trues.append(x)
        else:
            falses.append(x)
    return trues,falses

Мой вопрос: существует ли функциональная идиома программирования, которая выполняет это?

Ответы [ 5 ]

9 голосов
/ 13 сентября 2010

Из примеров itertools:

from itertools import tee, filterfalse
def partition(pred, iterable):
    t1, t2 = tee(iterable)
    return filterfalse(pred, t1), filter(pred, t2)
3 голосов
/ 13 сентября 2010

Hoogle - хороший инструмент для этого. Вы можете ввести тип функции и просмотреть все функции с этим типом. В этом случае нам нужны в качестве входных данных: список a и функция, которая принимает a и возвращает логическое значение, а вывод представляет собой пару списков a. В синтаксисе Haskell это (a -> Bool) -> [a] -> ([a], [a]). Оттуда мы видим соответствующую функцию раздел . Реализация:

partition p xs == (filter p xs, filter (not . p) xs)

В Python:

partition = lambda p, xs: (filter(p, xs), filter(lambda f: not p(f), xs))

Или это быстрее, но немного страшнее, потому что это асимметрично:

partition = lambda p, xs: (filter(p, xs), [z for z in xs if not p(z)])

Это действительно удваивает количество вычислений, которое вам нужно, но я думаю, что вы должны сделать это, если у вас нет мутации.

2 голосов
/ 13 сентября 2010

Вы можете сделать это с помощью сокращения, которое генерирует 2-элементный результат кортежа.

reduce(lambda x,y: (x[0]+[y],x[1]) if somefunc(y) else (x[0],x[1]+y), somelist, ([],[]))

Возвращает 2-кортеж; первая часть представляет собой список элементов, которые заставляют somefunc() возвращать значение True, вторая - остальные.

1 голос
/ 13 сентября 2010

Конечно, есть.На самом деле, он уже найден в Python.Посмотрите в itertools функцию групповой работы.Однако сначала вам придется отсортировать список по типу функции.Я вполне уверен, что это не то, что вам нужно, но это начало.

Я, я всегда реализовывал то, что вы просите через ifilter:

def multifilter( pred, arg ):
    return ifilter( pred, arg ), ifilter(lambda x: !pred(x), arg )
0 голосов
/ 30 марта 2013
trues = [x for x in seq if pred(x)]
falses = [x for x in seq if not pred(x)]

Это высота стиля функционального программирования, если вам не нужно больше вызовов функций.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...