C#函數(shù)式編程中的標(biāo)準(zhǔn)高階函數(shù)詳解
何為高階函數(shù)
大家可能對(duì)這個(gè)名詞并不熟悉,但是這個(gè)名詞所表達(dá)的事物卻是我們經(jīng)常使用到的。只要我們的函數(shù)的參數(shù)能夠接收函數(shù),或者函數(shù)能夠返回函數(shù),當(dāng)然動(dòng)態(tài)生成的也包括在內(nèi)。那么我們就將這類函數(shù)叫做高階函數(shù)。但是今天我們的標(biāo)題并不是高階函數(shù),而是標(biāo)準(zhǔn)高階函數(shù),既然加上了這個(gè)標(biāo)準(zhǔn),就意味著在函數(shù)式編程中有一套標(biāo)準(zhǔn)的函數(shù),便于我們每次調(diào)用。而今天我們將會(huì)介紹三個(gè)標(biāo)準(zhǔn)函數(shù),分別為Map、Filter、Fold。
Map
這個(gè)函數(shù)的作用就是將列表中的每項(xiàng)從A類型轉(zhuǎn)換到B類型,并形成一個(gè)新的類型。下面我們可以看看在FCSLib中是如何實(shí)現(xiàn)的:
相信很多人應(yīng)該都能夠看懂這段代碼,僅僅只是循環(huán)list數(shù)據(jù)。然后調(diào)用convert函數(shù)轉(zhuǎn)換,最后通過(guò)yield將其組成一個(gè)列表返回。下面我們通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)演示下如何使用這個(gè)標(biāo)準(zhǔn)高階函數(shù):
我們通過(guò)聲明了一個(gè)數(shù)組data,然后利用map函數(shù)將其中的ID提取出來(lái),單獨(dú)形成一個(gè)列表。
Filter
通過(guò)名字應(yīng)該能夠猜出他大概的含義了,就是用來(lái)過(guò)濾數(shù)據(jù)的。相信一些人能夠根據(jù)上面寫出這個(gè)標(biāo)準(zhǔn)高階函數(shù)的具體實(shí)現(xiàn),當(dāng)然這里不管讀者有沒(méi)有寫出,我們都來(lái)看看FCSLib中是如何實(shí)現(xiàn)的:
這里我們只是少了一個(gè)泛型參數(shù),對(duì)應(yīng)的第一參數(shù)的是能夠接收T類型返回bool類型的函數(shù)(Predicate也是.NET自帶的,可能我們用慣了Func和Action,并且利用Func<T,bool>也可以實(shí)現(xiàn)一樣的效果。),而語(yǔ)句主要是在循環(huán)后調(diào)用了predicate去判斷是否滿足條件,如果滿足條件則返回。
Fold
這個(gè)標(biāo)準(zhǔn)高階函數(shù)可能會(huì)比較難,因?yàn)樗譃榱俗笳郫B和右折疊兩種。接收的參數(shù)有三個(gè),分別是起始值,累加函數(shù),列表。大致的執(zhí)行過(guò)程就是在第一次調(diào)用我們的累加函數(shù)時(shí)將起始值作為一個(gè)參數(shù),而列表中的第一個(gè)值作為第二個(gè)參數(shù)去調(diào)用我們的累加函數(shù),累加函數(shù)計(jì)算出結(jié)果,而這個(gè)結(jié)果將作為下一次調(diào)用累加函數(shù)時(shí)的第一參數(shù),而第二個(gè)參數(shù)則是列表中的下一項(xiàng),以此類推。所以通過(guò)這個(gè)高階函數(shù)我們可以直接計(jì)算出列表中每項(xiàng)數(shù)據(jù)累加后的結(jié)果,而在FCSLib中的具體實(shí)現(xiàn)則如下所示:
通過(guò)查看源代碼我們也可以得出之前的執(zhí)行流程,在第一次的時(shí)候v的值為startValue,而之后就會(huì)將accmulator函數(shù)的返回值保存進(jìn)v,這樣下一次執(zhí)行accmulator時(shí)就作為第一個(gè)參數(shù)傳入。下面我們通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)看看如何使用:
左折疊完成之后對(duì)應(yīng)的還有一個(gè)右折疊,當(dāng)然根據(jù)名字也可以猜出。就是從list的末尾開(kāi)始進(jìn)行循環(huán),所以我們可以這樣來(lái)實(shí)現(xiàn)FoldR:
這里還要指出的就是左折疊和右折疊是最常用的算法之一,他完全可以實(shí)現(xiàn)像我們之前介紹過(guò)的Map和Filter,而只要按照下面這種方式寫即可:
這里我們就是利用Fold函數(shù)的一個(gè)特性來(lái)實(shí)現(xiàn)的,因?yàn)槔奂雍瘮?shù)每次都會(huì)將上一次計(jì)算得出的結(jié)果傳遞給下一個(gè)累加函數(shù)(new List<R>()我們直接將其作為起始值傳入),最后我們都會(huì)通過(guò)return x將這個(gè)列表返回,這樣下一次再調(diào)用這個(gè)累加函數(shù)之后x依然是同一個(gè)列表。對(duì)應(yīng)的還有Filter的實(shí)現(xiàn):
而具體的調(diào)用方式則和Map,F(xiàn)ilter是一致的,并沒(méi)有什么特別大的區(qū)別。
關(guān)于Linq中的Map、Filter和Fold
其實(shí)函數(shù)式編程已經(jīng)在不知不覺(jué)中慢慢的進(jìn)入到我們的生活中,其實(shí)我們經(jīng)常在Linq中使用的select、where和aggregate就是對(duì)應(yīng)著函數(shù)式編程中的map、filter和fold。
相關(guān)文章
c# 使用Entity Framework操作Access數(shù)據(jù)庫(kù)的示例
本篇文章主要介紹了c# 使用Entity Framework操作Access數(shù)據(jù)庫(kù)的示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11C# 如何設(shè)置label(標(biāo)簽)控件的背景顏色為透明
這篇文章主要介紹了C# 如何設(shè)置label(標(biāo)簽)控件的背景顏色為透明,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2020-10-10C#使用post發(fā)送和接收數(shù)據(jù)的方法
這篇文章主要介紹了C#使用post發(fā)送和接收數(shù)據(jù)的方法,涉及C#使用post收發(fā)數(shù)據(jù)的相關(guān)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04結(jié)合.net框架在C#派生類中觸發(fā)基類事件及實(shí)現(xiàn)接口事件
這篇文章主要介紹了結(jié)合.net框架在C#派生類中觸發(fā)基類事件及實(shí)現(xiàn)接口事件,示例的事件編程中包括接口和類的繼承等面向?qū)ο蟮幕A(chǔ)知識(shí),需要的朋友可以參考下2016-02-02