Python 在单个迭代期间应用多个自包含过滤器

Python 在单个迭代期间应用多个自包含过滤器,python,filter,functional-programming,Python,Filter,Functional Programming,假设我有一个数据结构,它的迭代成本非常高,我需要根据特定的标准将它的元素收集到列表中 #fake data. pretend it's hard to access import random slowStruct = range(30) random.shuffle(slowStruct) def check1(x): return x < 3 def check2(x): return x > 15 def check3(x): return x

假设我有一个数据结构,它的迭代成本非常高,我需要根据特定的标准将它的元素收集到列表中

#fake data.  pretend it's hard to access
import random
slowStruct = range(30)
random.shuffle(slowStruct)

def check1(x):
    return x < 3

def check2(x):
    return x > 15

def check3(x):
    return x < 25 and x > 20
更快的方法是使用循环并附加到结果列表:

res1 = []
res2 = []
res3 = []
for node in slowStruct:
    if check1(node):
        res1.append(node)
    if check2(node):
        res2.append(node)
    if check3(node):
        res3.append(node)
是否有一种函数式编程结构或习惯用法可以执行多个过滤器,而只使用一次迭代

我可以想象它看起来像:

res1, res2, res3 = multiFilter(preds=[check1, check2, check3], iterable=slowStruct)

没有一种干净的方法可以让你理解。如果需要循环,请使用循环。一份清单只能列出一份清单

如果您愿意使用循环,则允许您封装它:

def multi_filter(predicates, iterable):
    bins = [[] for _ in predicates]
    for item in iterable:
        for predicate, bin in zip(predicates, bins):
            if predicate(item):
                bin.append(item)

    return bins
是否有可以执行的函数式编程构造或习惯用法 多个过滤器,而只使用一个迭代

是的,您可以纯功能性地执行此操作(尽管您将达到最大递归深度,因为python不允许消除最后一个调用)。 下面的代码看起来很糟糕,纯粹是函数式的,只在iterable上迭代一次(但每次迭代都会迭代所有条件,这是不可避免的):

#/usr/bin/python3
slowStruct=[1,2,3,4,5,6,7,8,9,10]
条件=[lambda x:x<5,
λx:x%2,
λx:x%3]
多重过滤器=λpreds,可测试:(
lambda f,preds,iterable:f(
F
不可容忍的,
preds,
[[]用于preds中的[uuu]
)
) (
lambda f、l、cs、accs:f(
F
l[1:],
反恐精英,
[acc+(l[:1]如果c(l[0])否则[])
对于acc,邮政编码中的c(accs,cs)]
)如果我还有其他原因,
preds,
可迭代的
)
打印(多重过滤器(条件、slowStruct))
注:Python不是为函数式编程而设计的(参见LCO)。此外,PEP8对格式化功能代码没有帮助

所有评论:我不提倡这种编码风格,我只是尝试给出一个只使用一次迭代的功能实现(如OP所要求)。



编辑:如果考虑列表理解中的破坏性分配,可能不是纯粹的功能。

这是一个非常普通的问题的简单而简单的解决方案。我喜欢。
def multi_filter(predicates, iterable):
    bins = [[] for _ in predicates]
    for item in iterable:
        for predicate, bin in zip(predicates, bins):
            if predicate(item):
                bin.append(item)

    return bins
#! /usr/bin/python3

slowStruct = [1,2,3,4,5,6,7,8,9,10]
conditions = [lambda x: x < 5,
      lambda x: x % 2,
      lambda x: x % 3]

multiFilter = lambda preds, iterable: (
    lambda f, preds, iterable: f (
        f,
        iterable,
        preds,
        [ [] for _ in preds]
        )
    ) (
        lambda f, l, cs, accs: f (
            f,
            l [1:],
            cs,
            [acc + (l [:1] if c (l [0] ) else [] )
                for acc, c in zip (accs, cs) ]
        ) if l else accs,
        preds,
        iterable
    )

print (multiFilter (conditions, slowStruct) )