7.1.2 filter
Python內(nèi)建的filter()
函數(shù)用于過濾序列。
和map()
類似,filter()
也接收一個(gè)函數(shù)和一個(gè)序列。和map()
不同的是,filter()
把傳入的函數(shù)依次作用于每個(gè)元素,然后根據(jù)返回值是True
還是False
決定保留還是丟棄該元素。
例如,在一個(gè)list中,刪掉偶數(shù),只保留奇數(shù),可以這么寫:
把一個(gè)序列中的空字符串刪掉,可以這么寫:
可見用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è)方法是埃氏篩法,它的算法理解起來非常簡(jiǎn)單:
首先,列出從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ù)序列:
注意這是一個(gè)生成器,并且是一個(gè)無限序列。
然后定義一個(gè)篩選函數(shù):
最后,定義一個(gè)生成器,不斷返回下一個(gè)素?cái)?shù):
這個(gè)生成器先返回第一個(gè)素?cái)?shù)2
,然后,利用filter()
不斷產(chǎn)生篩選后的新的序列。
由于primes()
也是一個(gè)無限序列,所以調(diào)用時(shí)需要設(shè)置一個(gè)退出循環(huán)的條件:
注意到Iterator
是惰性計(jì)算的序列,所以我們可以用Python表示“全體自然數(shù)”,“全體素?cái)?shù)”這樣的序列,而代碼非常簡(jiǎn)潔。
小結(jié)
filter()
的作用是從一個(gè)序列中篩出符合條件的元素。由于filter()
使用了惰性計(jì)算,所以只有在取filter()
結(jié)果的時(shí)候,才會(huì)真正篩選并每次返回下一個(gè)篩出的元素。
上述實(shí)例若是不理解,可以參考詳解:
