Graddy
Graddy

Reputation: 3008

filtered and non-filtered elements in a single pass

Filter function returns a sublist of elements which return true for a given function. Is it possible to get the list of elements which return false in a different list without going over the entire list again.

Example:

trueList,falseList = someFunc(trueOrFalseFunc,list)

PS : I know it can be done by initializing two empty lists and appending elements to each based on the return value of the function. The list under consideration can be potentially very huge and there might very few elements that might return true. As the append function is costly, is there a better way to do it ?

Upvotes: 5

Views: 176

Answers (4)

Óscar López
Óscar López

Reputation: 236014

Try this, using iterators:

from itertools import tee

def partition(lst, pred):
    l1, l2 = tee((pred(e), e) for e in lst)
    return (x for cond, x in l1 if cond), (x for cond, x in l2 if not cond)

Use it like this, and remember that the values returned are iterators:

lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
evens, odds = partition(lst, lambda x: x%2 == 0)

If you need lists for some reason, then do this:

list(evens)
> [0, 2, 4, 6, 8]
list(odds)
> [1, 3, 5, 7, 9]

Upvotes: 5

ely
ely

Reputation: 77434

You could use generator comprehensions, which should help on performance and facilitate cleaner code. I really am not sure if this will be satisfactory for the rest of your program though. It depends on how you're using these returned results.

trueList = (elem for elem in list if trueOrFalseFunc(elem) )
falseList = (elem for elem in list if elem not in trueList )

Upvotes: 1

luke14free
luke14free

Reputation: 2539

If you want to go for a one liner you can do this: (I'm switching from dicts to lists as Niklas B. suggested to improve readability)

>>> some_list=[True, False, True, False, False]
>>> reduce(lambda (true,false),x: (true + [x], false) if x else (true, false + [x]), some_list, ([],[]))
([True, True], [False, False, False])

Upvotes: 2

Tim Pietzcker
Tim Pietzcker

Reputation: 336198

def someFunc(trueorfalsefunc, l):
    trueList = []
    falseList = []
    for item in l:
        if trueorfalsefunc(item):
            trueList.append(item)
        else:
            falseList.append(item)
    return trueList, falseList

So, for example:

>>> someFunc(bool, [1,2,0,"", "a"])
([1, 2, 'a'], [0, ''])

Upvotes: 3

Related Questions