(这是专业的最佳实践/模式兴趣,而非家庭工作要求)
INPUT :任何无序序列或生成器项,函数 myfilter(item)如果满足过滤条件则返回True
输出:(filter_true,filter_false)序列的元组 原始类型包含 按照分区划分的元素 按原始顺序过滤。
如果不进行双重过滤,您会如何表达这一点,还是应该使用双重过滤?也许过滤器和循环/生成器/列表comprehencion与next
可以回答?
我是否应该考虑保持类型或只是改变要求给出元组/发电机结果的元组,我不能轻易返回发电机输入发电机,或者我可以吗? (要求是自制的)
此时测试最佳候选人,提供两个流而不是元组
import itertools as it
from sympy.ntheory import isprime as myfilter
mylist = xrange(1000001,1010000,2)
left,right = it.tee((myfilter(x), x) for x in mylist)
filter_true = (x for p,x in left if p)
filter_false = (x for p,x in right if not p)
print 'Hundred primes and non-primes odd numbers'
print '\n'.join( " Prime %i, not prime %i" %
(next(filter_true),next(filter_false))
for i in range(100))
答案 0 :(得分:5)
以下是一种方法,只为每个项目调用myfilter
一次,如果mylist
是生成器,也可以使用
import itertools as it
left,right = it.tee((myfilter(x), x) for x in mylist)
filter_true = (x for p,x in left if p)
filter_false = (x for p,x in right if not p)
答案 1 :(得分:2)
让我们假设你的问题不是内存而是cpu,myfilter很重,你不想迭代和过滤两次原始数据集。以下是一些单一传递提示:
简单而通用的版本(记忆力很强):
filter_true=[]
filter_false=[]
for item in items:
if myfilter(item):
filter_true.append(item)
else:
filter_false.append(item)
内存友好版本:(不适用于生成器(除非与列表(项目)一起使用))
while items:
item=items.pop()
if myfilter(item):
filter_true.append(item)
else:
filter_false.append(item)
生成器友好版本:
while True:
try:
item=next(items)
if myfilter(item):
filter_true.append(item)
else:
filter_false.append(item)
except StopIteration:
break
答案 2 :(得分:0)
简单方法(但效率较低)是tee
迭代并过滤它们:
import itertools
left, right = itertools.tee( mylist )
filter_true = (x for x in left if myfilter(x))
filter_false = (x for x in right if myfilter(x))
这比最佳解决方案效率低,因为将为每个元素重复调用myfilter
。也就是说,如果您在left
中测试了一个元素,则不必在right
中重新测试它,因为您已经知道了答案。如果您需要此优化,则应该难以实现:查看tee
的实现以获取线索。你需要为每个返回的iterable提供一个双端队列,你可以使用原始序列的元素来存储它,但是还没有被要求。
答案 3 :(得分:-1)
我认为你最好的选择是建造两个独立的发电机:
filter_true = (x for x in mylist if myfilter(x))
filter_false = (x for x in mylist if not myfilter(x))