Short way to call ifilter with multiple predicates in python

I am passing a very large collection through a script and am currently using ifilterin a simple call to reject certain values, i.e.

ifilter(lambda x: x in accept_list, read_records(filename))

This predicate, but now it occurred to me that I should add one more, and I might want to add others in the future. A direct way would be to place a call ifilter:

ifilter(lambda x : x not in block_list,
    ifilter(lambda x: x in accept_list, read_records(filename)))

I mean just put the predicates as unrelated functions in a list and use them for this. These ifilter repeated calls seem difficult to reach there (and perhaps not the best option). Perhaps I can build one function that calls all the predicates, but how can I write this as concisely as possible (albeit still readable)?

+3
source share
3 answers

You can write the following function:

def conjoin(*fns):
    def conjoined(x):
        for fn in fns:
            if not fn(x): return False
        return True
    return conjoined

Then you call it like this:

ifilter(conjoined(lambda x: x not in block_list, lambda x: x in accept_list),
        read_records(filename))

And you can implement a similar function disjoinfor simultaneous functions:

def disjoin(*fns):
    def disjoined(x):
        for fn in fns:
            if fn(x): return True
        return False
    return disjoined

It might be better to implement them, but you need to be careful. You can try to apply each function to xand use allor any, but this is undesirable, since to use them you will need to evaluate each predicate in the argument. The solution presented here is a satisfactory short circuit.

In addition, just for fun, we implement the function invert

def invert(fn):
    return lambda x: not fn(x)

:)

+5

:

def complex_predicate(x):
    return x not in block_list and x in accept_list and is_good(x)

def complex_predicate2(x):
    return all([x not in block_list, x in accept_list, is_good(x)])

ifilter(complex_predicate, read_records(filename))

complex_predicate2.

, .

+1

If there are only two predicates, I would come up with the following:

ifilter(lambda x: x in accept_list and x not in block_list, read_records(filename))

In addition, as mentioned above, if there are more than two predicates, it is better to put all the predicates in a specific function. Use allmakes the condition block much less messy (since in this case all the predicates are separated by a comma).

0
source

Source: https://habr.com/ru/post/1752295/


All Articles