3

(这是专业的最佳实践/模式兴趣,不是家庭作业要求)

  • INPUT:任何无序序列或生成器项目,如果满足过滤条件,函数myfilter(item)返回 True

  • OUTPUT : (filter_true, filter_false)原始类型序列的元组,其中包含根据原始序列顺序的过滤器划分的元素。

如果不进行双重过滤,您将如何表达这一点,或者我应该使用双重过滤?也许过滤器和循环/生成器/列表理解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))
4

4 回答 4

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)
于 2010-09-06T10:45:01.213 回答
2

假设您的问题不是内存而是 cpu,myfilter 很重,并且您不想迭代和过滤原始数据集两次。以下是一些单次通过的想法:

简单而通用的版本(memoryvorous):

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
于 2010-09-06T10:45:00.447 回答
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线索。对于每个返回的可迭代对象,您都需要一个双端队列,您需要将原始序列的元素存储在其中,这些元素应该放入其中但尚未被要求。

于 2010-09-06T10:02:08.493 回答
-1

我认为你最好的选择是构建两个独立的生成器:

filter_true = (x for x in mylist if myfilter(x))
filter_false = (x for x in mylist if not myfilter(x))
于 2010-09-06T09:42:06.193 回答