zoukankan      html  css  js  c++  java
  • filter---埃氏筛法

    def _odd_iter():
        n = 1
        while True:
            n = n + 2
            yield n
    
    def _not_divisible(n):
        return lambda x: x % n > 0
    
    def primes():
        yield 2
        it = _odd_iter()
        while True:
            n = next(it)
            yield n
            it = filter(_not_divisible(n), it)
    
    for n in primes():
        if n < 1000:
            print(n)
        else:
            break
    

    学到了filter,看到这个埃氏筛法求质数的程序,觉得挺有意思的。

    思路如下:

    1、首先得到一个从3开始的奇数iterator it

    2、从iterator it中取首个数,该数为质数,第一轮即为3

    3、然后运用filter,其中筛选函数为_not_divisible(n),n=3,此时it已经去除了3,现在it为从5开始的奇数iterator

    4、筛选之后得到it=filter(_not_divisible(3),it)的Iterator

    5、然后继续循环,n=next(it),由于是Iterator,所以要一个,算一个,取it的第一个5放入filter(_not_divisible(3),it)筛选,返回5

    6、5为质数,打印5,然后继续运用filter,其中筛选函数为_not_divisible(n),n=5,此时it已经去除了5,现在it为不包含5的Iterator,filter(_not_divisible(5),filter(_not_divisible(3),it#注这里的it为最初的奇数Iterator))

    7、继续循环,n=next(it),取最初奇数Iterator的下一个元素7,首先先用3除筛选,再用5除筛选,返回7,7为质数,打印7

    8、然后继续运用filter,其中筛选函数为_not_divisible(n),n=7,此时it已经去除了7,现在it为不包含7的Iterator,filter(_not_dicisible(7),filter(_not_divisible(5),filter(_not_divisible(3),it#注这里的it为最初的奇数Iterator)))

    8、继续循环,n=next(it),取最初奇数Iterator的下一个元素9,首先先用3除筛选,丢弃9,再取下一个元素11,依次用3、5、7除,返回11,11为质数,打印11

    ...继续循环下去

    这里有一个问题,为什么不能把

    lambda x: x % n > 0
    

    直接放在filter中作为筛选函数呢?

    def odd_iter():
        n=1;
        while True:
            n+=2
            yield n
    
    def choise(n):
        return lambda x: print('check if', x, 'is divisible by', n, 'result: ', not (x % n > 0)) or x % n > 0
    
    def primes():
        yield 2
        it=odd_iter()
        k=0
        while k<100:
            n=next(it)
            yield n
            it=filter(lambda x: print('check if', x, 'is divisible by', n, 'result: ', not (x % n > 0)) or x % n > 0,it)
            k+=1
    for n in primes():
        if n<1000:
            print(n)
    

    输出结果如下:

    2
    3
    check if 5 is divisible by 3 result:  False
    5
    check if 7 is divisible by 5 result:  False
    check if 7 is divisible by 5 result:  False
    7
    check if 9 is divisible by 7 result:  False
    check if 9 is divisible by 7 result:  False
    check if 9 is divisible by 7 result:  False
    9
    check if 11 is divisible by 9 result:  False
    check if 11 is divisible by 9 result:  False
    check if 11 is divisible by 9 result:  False
    check if 11 is divisible by 9 result:  False
    11
    check if 13 is divisible by 11 result:  False
    check if 13 is divisible by 11 result:  False
    check if 13 is divisible by 11 result:  False
    check if 13 is divisible by 11 result:  False
    check if 13 is divisible by 11 result:  False
    13
    check if 15 is divisible by 13 result:  False
    check if 15 is divisible by 13 result:  False
    check if 15 is divisible by 13 result:  False
    check if 15 is divisible by 13 result:  False
    check if 15 is divisible by 13 result:  False
    check if 15 is divisible by 13 result:  False
    15
    check if 17 is divisible by 15 result:  False
    check if 17 is divisible by 15 result:  False
    check if 17 is divisible by 15 result:  False
    check if 17 is divisible by 15 result:  False
    check if 17 is divisible by 15 result:  False
    check if 17 is divisible by 15 result:  False
    check if 17 is divisible by 15 result:  False
    17
    check if 19 is divisible by 17 result:  False
    check if 19 is divisible by 17 result:  False
    check if 19 is divisible by 17 result:  False
    check if 19 is divisible by 17 result:  False
    check if 19 is divisible by 17 result:  False
    check if 19 is divisible by 17 result:  False
    check if 19 is divisible by 17 result:  False
    check if 19 is divisible by 17 result:  False
    19
    

    因为使用匿名函数筛选时,n始终都是之前yield的那个值

    这个程序关键点在于每个Iterator经过筛选,又需要再次筛选,但并不是一步到位筛选,因为不是列表,而是在next的时候进行计算,类似递归

    作业如下:

    回数是指从左向右读和从右向左读都是一样的数,例如12321909。请利用filter()滤掉非回数:

    def is_palindrome(n):
        c=0
        i=n
        while i>=1:
            c*=10
            c+=i%10
            i=int(i/10)
            print(c)
        return c==n
    output = filter(is_palindrome, range(1, 1000))
    print(list(output))
    

    回数还可以通过将回数变为字符串根据字符比较来判断,代码非常简洁  

    def is_palindrome(n):
        return str(n)==str(n)[::-1]
    output = filter(is_palindrome, range(1, 100))
    print(list(output))
    

      

  • 相关阅读:
    字典树Trie
    转载一个不错的LRU cache
    git和github基础入门
    git基础之常用操作
    python矩阵和向量的转置问题
    梯度下降法注意要点
    python 浮点数问题
    Python数据分析基础——读写CSV文件2
    Python数据分析基础——读写CSV文件
    读书笔记----javascript函数编程
  • 原文地址:https://www.cnblogs.com/vonkimi/p/6895843.html
Copyright © 2011-2022 走看看