• 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))
    

      

  • 相关阅读:
    DHCP原理和配置
    汇编学习1--寄存器学习
    关于ZF2中一点感悟,service_manager
    PHP太怪了,in_array() ,strpos,
    MySql中的skip-name-resovle
    好几天没有写随笔了,今天打开了,随便留点什么吧
    今天是第二次登录,随便写点东西
    我的博客开通了.....,以前也开通了博客,但从来都没有写过,从今天起,希望自己能坚持下去,不断的积累自己技术水平
    luogu 1258 小车问题 小学奥数(?)
    luogu 3406 海底高铁 前缀和
  • 原文地址:https://www.cnblogs.com/vonkimi/p/6895843.html
Copyright © 2020-2023  润新知