假设我有一个迭代非常昂贵的数据结构,我需要根据某些标准将其元素收集到列表中。
#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
最简单的方法是使用列表推导。但这需要在结构中进行3次迭代:
res1 = [node for node in slowStruct if check1(node)]
res2 = [node for node in slowStruct if check2(node)]
res3 = [node for node in slowStruct if check3(node)]
更快的方法是使用循环并附加到结果列表:
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)
答案 0 :(得分:2)
理解并没有一种干净的方式。如果你想要一个循环,请使用循环。列表理解应该只列出一个列表。
如果您愿意使用循环,则允许封装它:
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
答案 1 :(得分:1)
是否有可以执行的功能编程结构或习惯用法 多个过滤器,只使用一次迭代?
是的,你可以做到这一点纯功能(虽然你会达到最大递归深度,因为python不允许最后一次调用消除)。 下面的代码看起来很糟糕,纯粹是函数式的,只在iterable上迭代一次(但是迭代遍历每次迭代的所有条件,这是不可避免的):
#! /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) )
Nota bene:Python不是用于函数式编程(参见LCO)。此外,PEP8无法格式化功能代码。
对于所有评论者:我不提倡这种编码风格,我只是试图给出一个只使用一次迭代的功能实现(按照OP的要求)。
编辑:如果你考虑列表理解中的破坏性赋值,可能不是纯粹的功能。