Python3之高阶函数filter

  Python内建的filter()函数用于过滤序列

  和map()一样,filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃改元素

  例如,在一个list中,删掉偶数,保留奇数

>>> def is_odd(n):
...   return n%2==1
... 
>>> list(filter(is_odd,[1,2,3,4,5,6,7]))
[1, 3, 5, 7]

  把序列作为参数传递至函数is_odd()如果参数为奇数则返回True则保留,如果参数为偶数则返回False则不保留

  把一个序列中的空字符删除

>>> def is_empty(s):
...   return s and s.strip()
>>> list(filter(is_empty,['1','',None,' ','zhangs']))
['1', 'zhangs']

  函数is_empty返回为s and s.strip()及字符不为空则返回为True否则为False

 

  注意到filter()函数返回的是一个Iterator,也就是一个惰性序列,所以要强迫filter()完成计算结果,需要用list()函数获得所有结果并返回list。

  用filter求素数,素数定义:指整数在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数

  计算素数的一个方法是埃氏筛法 算法如下

  首先列出从2开始的自然数构成一个无限序列:

  2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20...

  取序列的第一个数2一定是一个素数,然后用2筛选序列能被2整除的去掉,不能被2整除的保留

       2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20...

  保留下来的序列为

  3,5,7,9,11,13,15,17,19...

  取新序列的第一个数3一定是一个素数,然后用3筛选序列能被3整除的数去掉,不能被3整除的保留

       3,5,7,9,11,13,15,17,19...

  保留下来的序列为

  5,7,11,13,17,19...

  然后去新序列的第一个数5一定是一个素数 ,筛选,以此类推不断筛选下去就能得到所有素数

  

  第一个素数是2 第一次筛选就可以把所有偶数剔除

  定义一个已3开始的奇数序列

>>> def _odd_iter():
...   n=3
...   while True:
...     yield n
...     n=n+2
... 

  定义_odd_iter()函数,函数定义n初始值为3 ,ywhile True 无限循环,yield生成器返回序列第一个数为3然后n递增2,以此类推

  输出以3开始的奇数序列,因为_odd_iter()是一个无限序列所有需要设置一个退出循环的条件

>>> for n in _odd_iter():
...   if n<100:
...     print(n)
...   else:
...     break

  输出以3开始小于100的奇数

  

  定义筛选函数不能被整除

>>> def _not_divislibe(n):
...   def f(x):
...     return x%n>0
...   return f

  这里函数调用返回的还是函数,需要在调用的时候才执行,例如调用

fun1=_not_divisible(2)

  相当于调用函数后参数n=2返回函数fun1=f,返回函数不会立即执行需要在调用的时候才执行,调用的时候加参数x判断x能否整除n,如果可以整除则x%n==0 不满足条件x%n>0所以返回False,不能整除则返回为True

#2可以被4整除返回为False
>>> fun1(4)
False
#2不能被5整除 5%2=1>0
>>> fun1(5)
True

  关于返回函数查看https://www.cnblogs.com/minseo/p/11064421.html

  最后定义一个生成器primes()不断返回素数

>>> def primes():
#先返回第一个素数2
...   yield 2
#把从3开始的无限奇数序列赋值给序列it
...   it=_odd_iter()
...   while True:
#返回序列的第一个数一定是素数
...     n=next(it)
...     yield n
#把第一个数当成被除数,使用序列如果不能被整除则保留下来
...     it=filter(_not_divislibe(n),it)

  设置一个条件打印出来,打印出小于100的素数

>>> for n in primes():
...   if n<100:
...     print(n)

  

   从2开始构建自然数序列写法

  primes()

#构建以2开始的自然数序列
def _natural_iter():
    n=2
    while True:
        yield n
        n=n+1

#定义不能被整除函数
def _not_divisible(n):
    return lambda x:x%n>0

#定义素数函数
def primes():
    #把从2开始的自然数赋值给序列it
    it=_natural_iter()
    while True:
        #去序列第一个数一定是素数作为生成器的返回
        n=next(it)
        yield n
        #把序列的第一位数作为被除数依次使用后面的数如果能被整除则删除,不能被整除则保留
        #例如第一次使用filter过滤及把偶数过滤掉剩下的为从3开始的所有奇数
        it=filter(_not_divisible(n),it)

for n in primes():
    if n<100:
        print(n)
    else:
        break

  

   练习:回数是至从左往右读和从右往左都都是一样的数,例如1,11,121,12321.利用filter筛选出回数

      思路:定义一个函数传递的参数为整数n,把n转换成字符串,然后反转与初始字符串对比,如果一样就代表是回数

  

 is_palindrome.py

  

def is_palindrome(n):
    #str(n)把整数转换成字符串使用切片法反转
    #例如s='123'则s[::-1]='321'
    #如果反转后与反转前是一致则返回True
    return str(n)==str(n)[::-1]

#打印1-1999之间所有回数
print(list(filter(is_palindrome,range(1,2000))))

  结果

[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191, 202, 212, 222, 232, 242, 252, 262, 272, 282, 292, 303, 313, 323, 333, 343, 353, 363, 373, 383, 393, 404, 414, 424, 434, 444, 454, 464, 474, 484, 494, 505, 515, 525, 535, 545, 555, 565, 575, 585, 595, 606, 616, 626, 636, 646, 656, 666, 676, 686, 696, 707, 717, 727, 737, 747, 757, 767, 777, 787, 797, 808, 818, 828, 838, 848, 858, 868, 878, 888, 898, 909, 919, 929, 939, 949, 959, 969, 979, 989, 999, 1001, 1111, 1221, 1331, 1441, 1551, 1661, 1771, 1881, 1991]

  字符串反转参考:https://www.cnblogs.com/minseo/p/11065920.html

  

  

posted @ 2019-06-20 16:51  minseo  阅读(558)  评论(0编辑  收藏  举报