Is there a functional programming idiom for filtering a list into truths and falsehoods?

Let's say you have a list L , and you want to split it into two lists based on some logical function P That is, you need one list of all the elements of L , where P(l) is true, and another list where P(l) is false.

I can implement this in Python like this:

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

My question is: is there a functional programming idiom that does this?

+7
python filter functional-programming
source share
5 answers

From the itertools examples:

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

Hoogle is a good tool for this. You can enter a function type and view all functions with this type. In this case, we need an input: a list a and a function that takes a and returns a boolean, and the output is a pair of a lists. In the Haskell syntax, which (a -> Bool) -> [a] -> ([a], [a]) . From there we see the corresponding partition function. Implementation:

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

In Python:

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

Or itโ€™s faster, but a little uglier causes asymmetry:

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

This makes twice the calculation you need, but I think you should do it if you don't have a mutation.

+3
source share

You can do this with a shorthand that generates the result from a 2-element tuple.

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

Returns a 2-tuple; the first part is a list of elements that make somefunc() return True, the second is the rest.

+2
source share

Of course have. In fact, Python already has one. Look under itertools for the groupby function. However, you will first have to sort the list by function type. I am sure that this is not what you need, but this is the beginning.

I, I always did what you ask through ifilter :

 def multifilter( pred, arg ): return ifilter( pred, arg ), ifilter(lambda x: !pred(x), arg ) 
+1
source share
 trues = [x for x in seq if pred(x)] falses = [x for x in seq if not pred(x)] 

This is the height of the functional programming style if you don't want more function calls.

0
source share

All Articles