本文作者:黎智煊休蟹,叩丁狼高級講師。原創(chuàng)文章肤视,轉(zhuǎn)載請注明出處。
filter()函數(shù)
Python內(nèi)建的filter()
函數(shù)用于過濾序列涉枫。
和map()
類似邢滑,filter()
也接收一個(gè)函數(shù)和一個(gè)序列。和map()
不同的是拜银,filter()
把傳入的函數(shù)依次作用于每個(gè)元素殊鞭,然后根據(jù)返回值是True
還是False
決定保留還是丟棄該元素遭垛。
例如尼桶,在一個(gè)list中,刪掉偶數(shù)锯仪,只保留奇數(shù)泵督,可以這么寫:
def is_odd(n):
return n % 2 == 1
list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
# 結(jié)果: [1, 5, 9, 15]
把一個(gè)序列中的空字符串刪掉,可以這么寫:
def not_empty(s):
return s and s.strip()
list(filter(not_empty, ['A', '', 'B', None, 'C', ' ']))
# 結(jié)果: ['A', 'B', 'C']
可見用filter()
這個(gè)高階函數(shù)庶喜,關(guān)鍵在于正確實(shí)現(xiàn)一個(gè)“篩選”函數(shù)小腊。
注意到filter()
函數(shù)返回的是一個(gè)Iterator
,也就是一個(gè)惰性序列久窟,所以要強(qiáng)迫filter()
完成計(jì)算結(jié)果秩冈,需要用list()
函數(shù)獲得所有結(jié)果并返回list。
用filter求素?cái)?shù)
計(jì)算素?cái)?shù)的一個(gè)方法是埃氏篩法斥扛,它的算法理解起來非常簡單:
首先入问,列出從2
開始的所有自然數(shù),構(gòu)造一個(gè)序列:
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...
取序列的第一個(gè)數(shù)2
稀颁,它一定是素?cái)?shù)芬失,然后用2
把序列的2
的倍數(shù)篩掉:
3, ~~4~~, 5, ~~6~~, 7, ~~8~~, 9, ~~10~~, 11, ~~12~~, 13, ~~14~~, 15, ~~16~~, 17, ~~18~~, 19, ~~20~~, ...
取新序列的第一個(gè)數(shù)3
,它一定是素?cái)?shù)匾灶,然后用3
把序列的3
的倍數(shù)篩掉:
5, ~~6~~, 7, ~~8~~, ~~9~~, ~~10~~, 11, ~~12~~, 13, ~~14~~, ~~15~~, ~~16~~, 17, ~~18~~, 19, ~~20~~, ...
取新序列的第一個(gè)數(shù)5
棱烂,然后用5
把序列的5
的倍數(shù)篩掉:
7, ~~8~~, ~~9~~, ~~10~~, 11, ~~12~~, 13, ~~14~~, ~~15~~, ~~16~~, 17, ~~18~~, 19, ~~20~~, ...
不斷篩下去,就可以得到所有的素?cái)?shù)阶女。
用Python來實(shí)現(xiàn)這個(gè)算法颊糜,可以先構(gòu)造一個(gè)從3
開始的奇數(shù)序列:
def _odd_iter():
n = 1
while True:
n = n + 2
yield n
注意這是一個(gè)生成器,并且是一個(gè)無限序列秃踩。
然后定義一個(gè)篩選函數(shù):
def _not_divisible(n):
return lambda x: x % n > 0
最后芭析,定義一個(gè)生成器,不斷返回下一個(gè)素?cái)?shù):
def primes():
yield 2
it = _odd_iter() # 初始序列
while True:
n = next(it) # 返回序列的第一個(gè)數(shù)
yield n
it = filter(_not_divisible(n), it) # 構(gòu)造新序列
這個(gè)生成器先返回第一個(gè)素?cái)?shù)2
吞瞪,然后馁启,利用filter()
不斷產(chǎn)生篩選后的新的序列拾稳。
由于primes()
也是一個(gè)無限序列,所以調(diào)用時(shí)需要設(shè)置一個(gè)退出循環(huán)的條件:
# 打印1000以內(nèi)的素?cái)?shù):
for n in primes():
if n < 1000:
print(n)
else:
break
注意到Iterator
是惰性計(jì)算的序列最欠,所以我們可以用Python表示“全體自然數(shù)”荚斯,“全體素?cái)?shù)”這樣的序列,而代碼非常簡潔霉颠。
想獲取更多技術(shù)干貨对碌,請前往叩丁狼官網(wǎng):http://www.wolfcode.cn/all_article.html