在python中使用多个谓词调用ifilter的简洁方法

时间:2010-06-29 15:01:02

标签: python functional-programming iterator

我正在通过脚本流式传输一个非常大的集合,目前正在使用ifilter进行简单的调用以拒绝某些值,即:

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

这是一个谓词,但现在我发现我应该添加另一个谓词,我可能希望将来添加其他谓词。直截了当的方式是嵌套ifilter电话:

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

我正在考虑简单地将谓词作为未绑定的函数放在列表中并使用它们。虽然这些重复的ifilter调用似乎很难实现(并且可能不是最佳选择)。也许我可以构造一个调用所有谓词的函数,但是如何尽可能简洁地(尽管仍然可读)编写它?

3 个答案:

答案 0 :(得分:5)

您可以编写以下函数:

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

然后你会这样称呼它:

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

您可以同时为 -ing函数实现类似的disjoin函数:

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

可能有更好的方法来实现它们,但必须要小心。有人可能会尝试将每个函数应用于x并使用allany,但这是不可取的,因为使用它们需要评估参数的每个谓词。这里提出的解决方案是令人满意的短路。

另外,为了好玩,让我们实现一个invert函数

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

现在,我们有一组functionally complete函数操作函数,可以构造任何逻辑运算:)

答案 1 :(得分:1)

我会坚持使用以下解决方案:

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相同。

但是,我认为这是一个品味问题。

答案 2 :(得分:0)

如果只有两个谓词,我会想出以下内容:

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

另外,如上所述,如果有两个以上的谓词,最好将所有谓词放在特定的函数中。 使用all会使条件块变得更加混乱(因为在这种情况下所有谓词都用逗号分隔)。