作者:Jonathan Hsu
編譯:ronghuaiyang
導(dǎo)讀
想不想去掉瀑布一樣的For循環(huán)?使用函數(shù)式編程來(lái)寫(xiě)代碼。
你有沒(méi)有過(guò)看自己的代碼的時(shí)候,看到瀑布一樣的 for 循環(huán)?你是否發(fā)現(xiàn)自己不得不瞇著眼睛,向顯示器前傾才能看得更清楚?
我知道我有過(guò)。
For 循環(huán)是解決問(wèn)題的瑞士軍刀,但是,當(dāng)需要瀏覽代碼以快速閱讀你所做的事情時(shí),它們可能會(huì)讓人不知所措。
有三種技術(shù) — map、filter 和 reduce — 可以通過(guò)描述如何進(jìn)行迭代來(lái)代替 for 訓(xùn)練。JavaScript 中也有這些技術(shù),但是在 Python 中的實(shí)現(xiàn)略有不同。
我們將簡(jiǎn)要介紹這三種技術(shù)中的每一種,強(qiáng)調(diào)它們?cè)?JavaScript 和 Python 中的語(yǔ)法差異,然后給出如何轉(zhuǎn)換普通 for 循環(huán)的示例。
什么是 Map, Filter, 以及 Reduce?
回顧之前寫(xiě)的代碼,我發(fā)現(xiàn)在 95%的情況下,當(dāng)循環(huán)遍歷字符串或數(shù)組時(shí),我是這樣做的:將序列map到每個(gè)值,filter滿足特定條件的值,或者將數(shù)據(jù)集reduce到單個(gè)聚合值。
有了這樣的認(rèn)識(shí),這三種方法就是識(shí)別 —— 然后實(shí)現(xiàn),你遍歷 iterable 的原因通常屬于這三種功能中的一種:
Map:對(duì)每個(gè)一項(xiàng)應(yīng)用相同步驟的操作,然后存儲(chǔ)結(jié)果。
Filter:應(yīng)用驗(yàn)證標(biāo)準(zhǔn),存儲(chǔ)評(píng)估為真的項(xiàng)。
Reduce:返回一個(gè)在元素之間傳遞的值。
Python 中 Map/Filter/Reduce 的不同點(diǎn)是什么?
在 Python 中,這三種技術(shù)以函數(shù)的形式存在,而不是以數(shù)組或字符串類(lèi)的方法。這意味著不要寫(xiě)成my_array.map(function),而要寫(xiě)成map(function, my_list)。
此外,每種技術(shù)都需要傳遞一個(gè)函數(shù),該函數(shù)將為每個(gè)一項(xiàng)執(zhí)行。通常,函數(shù)被寫(xiě)成匿名函數(shù)(在 JavaScript 中稱(chēng)為胖箭頭函數(shù))。但是,在 Python 中經(jīng)常看到使用 lambda 表達(dá)式。
lambda 表達(dá)式和箭頭函數(shù)之間的語(yǔ)法實(shí)際上非常相似。將' => '替換為':',并確保使用關(guān)鍵字' lambda ',其余內(nèi)容幾乎相同。
// JavaScript Arrow Function const square = number => number * number; // Python Lambda Expression square = lambda number: number * number
箭頭函數(shù)和 lambda 表達(dá)式之間的一個(gè)關(guān)鍵區(qū)別是,箭頭函數(shù)可以擴(kuò)展成包含多條語(yǔ)句的完整函數(shù),而 lambda 表達(dá)式則被限制為返回的單個(gè)表達(dá)式。因此,在使用map()、filter()或reduce() 的時(shí)候,如果你需要對(duì)每個(gè)項(xiàng)執(zhí)行多個(gè)操作,那么首先定義函數(shù),然后將其包含進(jìn)來(lái)。
def inefficientSquare(number): result = number * number return result map(inefficientSquare, my_list)
替換 For 循環(huán)
好吧,說(shuō)正事。下面是三個(gè)常見(jiàn)的 for 循環(huán)示例,它們將被 map、filter 和 reduce 替換。我們的編程提示:計(jì)算列表中奇數(shù)的平方和。
首先,使用 basic for 循環(huán)的例子。注意:這純粹是為了演示,甚至可以在沒(méi)有 map/filter/reduce 的情況下進(jìn)行改進(jìn)。
numbers = [1,2,3,4,5,6] odd_numbers = [] squared_odd_numbers = [] total = 0 # filter for odd numbers for number in numbers: if number % 2 == 1: odd_numbers.append(number) # square all odd numbers for number in odd_numbers: squared_odd_numbers.append(number * number) # calculate total for number in squared_odd_numbers: total += number # calculate average
讓我們把每一步轉(zhuǎn)換為一個(gè)函數(shù):
from functools import reduce numbers = [1,2,3,4,5,6] odd_numbers = filter(lambda n: n % 2 == 1, numbers) squared_odd_numbers = map(lambda n: n * n, odd_numbers) total = reduce(lambda acc, n: acc + n, squared_odd_numbers)
有幾個(gè)重要的語(yǔ)法點(diǎn)需要突出顯示。
map()和filter()是本地可用的。但是,reduce()必須從 Python 3+的functools庫(kù)中導(dǎo)入。
lmbda 表達(dá)式是所有三個(gè)函數(shù)中的第一個(gè)參數(shù),而 iterable 是第二個(gè)參數(shù)
reduce()的 lambda 表達(dá)式需要兩個(gè)參數(shù):累加器(傳遞給每個(gè)元素的值)和單個(gè)元素本身。
編輯:hfy
-
顯示器
+關(guān)注
關(guān)注
21文章
5002瀏覽量
140249 -
python
+關(guān)注
關(guān)注
56文章
4805瀏覽量
84926
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論