假设您有一些列表L
,并且您希望根据一些布尔函数P
将其拆分为两个列表。也就是说,您需要一个包含l
为P(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
我的问题:是否有一个函数式编程习惯用来完成这个?
答案 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)]
这是功能编程风格的高度,除非你想要更多的函数调用。