是否有一个函数式编程习惯用于将列表过滤为真实和谬误?

时间:2010-09-13 02:27:06

标签: python functional-programming filter

假设您有一些列表L,并且您希望根据一些布尔函数P将其拆分为两个列表。也就是说,您需要一个包含lP(l)的所有元素的列表,以及另一个P(l)为假的列表。

我可以在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 个答案:

答案 0 :(得分:9)

来自itertools的例子:

from itertools import tee, filterfalse
def partition(pred, iterable):
    t1, t2 = tee(iterable)
    return filterfalse(pred, t1), filter(pred, t2)

答案 1 :(得分:3)

Hoogle是一个很好的工具。您可以输入函数类型并查看该类型的所有函数。在这种情况下,我们需要作为输入:a的列表,以及采用a并返回布尔值的函数,输出是a的一对列表。在Haskell语法中(a -> Bool) -> [a] -> ([a], [a])。从那里我们看到相关函数是partition。实现:

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 :(得分:2)

您可以使用reduce生成2元素元组结果。

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

返回2元组;第一部分是使somefunc()返回True的元素列表,第二部分是其余部分。

答案 3 :(得分:1)

当然有。事实上,已经有一个在Python中找到的。在itertools下查看groupby函数。但是,您必须首先按功能类型对列表进行排序。我很确定这不是你想要的,但它是一个开始。

我,我总是通过ifilter实施您要求的内容:

def multifilter( pred, arg ):
    return ifilter( pred, arg ), ifilter(lambda x: !pred(x), arg )

答案 4 :(得分:0)

trues = [x for x in seq if pred(x)]
falses = [x for x in seq if not pred(x)]

这是功能编程风格的高度,除非你想要更多的函数调用。