Python基础——filter函数

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

例如,在一个list中,删掉偶数,只保留奇数,可以这么写:

def is_odd(n):
    return n%2==1
print(list(filter(is_odd,[1,2,4,5,6,9,10,15])))
输出
[1, 5, 9, 15]

把一个序列中的空字符串删掉,可以这么写:

def not_empty(s):
    return s and s.strip()
print(list(filter(not_empty,['A','B','',None,'C',' '])))
输出
['A', 'B', 'C']

strip()方法是将字符串中首尾指定的字符去掉

s='  A '
print(s.strip())
输出
A

可见用filter()这个高阶函数,关键在于正确实现一个“筛选”函数。注意到filter()函数返回的是一个Iterator,也就是一个惰性序列,所以要强迫filter()完成计算结果,需要用list()函数获得所有结果并返回list。

用filter求素数

计算素数的一个方法是埃氏筛法,它的算法理解起来非常简单:

首先,列出从2开始的所有自然数,构造一个序列:

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

取序列的第一个数2,它一定是素数,然后用2把序列的2的倍数筛掉:

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

取新序列的第一个数3,它一定是素数,然后用3把序列的3的倍数筛掉:

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

取新序列的第一个数5,然后用5把序列的5的倍数筛掉:

7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...

不断筛下去,就可以得到所有的素数。

用Python来实现这个算法,可以先构造一个从3开始的奇数序列:

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) #返回序列的第一个数
        print(n)
        yield n
        it=filter(_not_divisible(n),it) #构造新序列

 这个生成器先返回第一个素数2,然后,利用filter()不断产生筛选后的新的序列。

由于primes()也是一个无限序列,所以调用时需要设置一个退出循环的条件:

for n in primes():
    if n<1000:
        print(n)
    else:
        break
输出
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
101
103
107
109
113
127
131
137
139
149
151
157
163
167
173
179
181
191
193
197
199
211
223
227
229
233
239
241
251
257
263
269
271
277
281
283
293
307
311
313
317
331
337
347
349
353
359
367
373
379
383
389
397
401
409
419
421
431
433
439
443
449
457
461
463
467
479
487
491
499
503
509
521
523
541
547
557
563
569
571
577
587
593
599
601
607
613
617
619
631
641
643
647
653
659
661
673
677
683
691
701
709
719
727
733
739
743
751
757
761
769
773
787
797
809
811
821
823
827
829
839
853
857
859
863
877
881
883
887
907
911
919
929
937
941
947
953
967
971
977
983
991
997

注意到Iterator是惰性计算的序列,所以我们可以用Python表示“全体自然数”,“全体素数”这样的序列,而代码非常简洁。

练习

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

def is_palindrome(n):
    n=str(n)#转换为字符串
    return n==n[::-1]#将字符串反转
print(list(filter(is_palindrome,range(1,1000))))
输出
[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]

参考源码:

https://github.com/mcttn1/python/blob/master/filter.py

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值