2014-09-19 131 views
0

我試圖通過過濾出複合數字來無休止地生成素數。使用列表來存儲和測試所有素數使整個事情變得緩慢,所以我嘗試使用生成器。過濾另一個過濾器對象

from itertools import count 
def chk(it,num): 
    for i in it: 
     if i%num: 
      yield(i) 
genStore = [count(2)] 
primeStore = [] 
while 1: 
    prime = next(genStore[-1]) 
    primeStore.append(prime) 
    genStore.append(chk(genStore[-1],num)) 

它工作的很好,生成素數,直到達到最大遞歸深度。 所以我找到了ifilter(或在python 3中過濾)。 從documentation of python standard library

作出這樣的過濾來自迭代只返回那些其斷言爲true元素的迭代器。如果謂詞是None,則返回true的項目。等效於:

def ifilter(predicate, iterable): 
    # ifilter(lambda x: x%2, range(10)) --> 1 3 5 7 9 
    if predicate is None: 
     predicate = bool 
    for x in iterable: 
     if predicate(x): 
      yield x 

,所以我得到以下幾點:

from itertools import count 
genStore = [count(2)] 
primeStore = [] 
while 1: 
    prime = next(genStore[-1]) 
    primeStore.append(prime) 
    genStore.append(filter(lambda x:x%num,genStore[-1])) 

我有望獲得:

2 
3  
5 
7 
11 
13 
17 
... 

我得到的是:

2 
3 
4 
5 
6 
7 
... 

它似乎next()只能遍歷count(),而不是過濾器。列表中的對象應該指向對象,所以我預計它的工作原理類似於filter(lambda x: x%n,(.... (filter(lambda x:x%3,filter(lambda x:x%2,count(2))))。我做了一些實驗,發現以下特點:

  1. filter(lambda x:x%2,filter(lambda x:x%3,count(0)))#works,過濾所有2 * n和3 * N
  2. genStore = [count(2)]; genStore.append(filter(lambda x:x%2,genStore[-1])); genStore.append (filter(lambda x:x%2,genStore[-1])) - 作品,也過濾所有2 * n和3 * N
  3. next(filter(lambda x:x%2,filter(lambda x:x%3,count(2)))) - 作品,打印出5

對比度:

from itertools import count 
genStore = [count(2)] 
primeStore = [] 
while 1: 
    prime = next(genStore[-1]) 
    print(prime) 
    primeStore.append(prime) 
    genStore.append(filter(lambda x:x%prime,genStore[-1])) 
    if len(genStore) == 3: 
     for i in genStore[-1]: 
      print(i) 
#It doesn't work, only filtering out 4*n. 

問題:

  • 它爲什麼不起作用?
  • 它是python的一個特性,或者我在某處犯了錯誤?
  • 有什麼辦法解決它?

回答

0

我認爲你的問題源於這樣一個事實,即lambda沒有被評估,它會'太晚',然後你會得到素數相同的所有他們,因爲他們都指向相同的變量。

你可以嘗試添加自定義過濾器和正常使用功能的,而不是拉姆達:

def myfilt(f, i, p): 
    for n in i: 
     print("gen:", n, i) 
     if f(n, p): 
      yield n 

def byprime(x, p): 
    if x % p: 
     print("pri:", x, p) 
     return True 

f = myfilt(byprime, genStore[-1], prime) 

這樣你可以避免lambda表達式存在的問題都是一樣的

+0

它仍然給時素數是最大遞歸錯誤變大了。我使用ifilter的原因是爲了避免這個錯誤。 – tamyiuchau 2014-09-20 01:53:06

+0

我認爲它會不管你使用什麼,因爲在某些時刻素數的密度下降到非常低的水平,所以這是這個解決方案的侷限性,當你使用懶惰濾波時你無法擺脫 – user3012759 2014-09-22 09:48:28