Скажем, у вас есть список 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

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

7
perimosocordiae 13 Сен 2010 в 06:27

5 ответов

Лучший ответ

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

from itertools import tee, filterfalse
def partition(pred, iterable):
    t1, t2 = tee(iterable)
    return filterfalse(pred, t1), filter(pred, t2)
8
Alex B 13 Сен 2010 в 02:36

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

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

def multifilter( pred, arg ):
    return ifilter( pred, arg ), ifilter(lambda x: !pred(x), arg )
0
wheaties 13 Сен 2010 в 02:32
trues = [x for x in seq if pred(x)]
falses = [x for x in seq if not pred(x)]

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

1
SteveWithamDuplicate 29 Июн 2014 в 20:01

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

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

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

1
Amber 13 Сен 2010 в 02:35

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
Claudiu 13 Сен 2010 в 02:48