最近,因?yàn)楣拘枰貥?gòu)一個(gè)項(xiàng)目,我們同事遇到一個(gè)需求,本來(lái)這部分事情是后端做的現(xiàn)在放到前端來(lái),這個(gè)需求是這樣的,項(xiàng)目中經(jīng)常能遇到關(guān)于城市列表的數(shù)據(jù),此數(shù)據(jù)像這個(gè)樣子

這是原始數(shù)據(jù),需要我們前端進(jìn)行按首字母來(lái)分組,變成下面的樣子

這對(duì)于我們來(lái)說(shuō)也許不難,但是得到相同的結(jié)果,采取的方式不同代碼量,和可維護(hù)性不盡相同,可能每個(gè)人解決的方式不一樣。下面說(shuō)一下我同事是怎么實(shí)現(xiàn)現(xiàn)的。


因?yàn)楸救吮容^喜歡函數(shù)式編程,喜歡把具體的細(xì)節(jié)封裝在函數(shù)里,所以平時(shí)也會(huì)喜歡使用數(shù)組比較“函數(shù)式的api”, 我會(huì)這樣解決上面的問(wèn)題

這段代碼同樣可以獲取到字母集合。接下來(lái)就是比較關(guān)鍵的一步了,同事采取的方法是遍歷字母數(shù)組,以及城市數(shù)組,匹配城市的字母和數(shù)組里面的字母是否相等,如果相等,就在此字母對(duì)應(yīng)的數(shù)組里面push此城市,且看代碼

結(jié)果是正確的,按照字母進(jìn)行分組了

但其實(shí)這樣會(huì)不會(huì)太繁瑣了,首先傳統(tǒng)的for循環(huán)可是使用foreach來(lái)代替,其次如果不是雙層遍歷,對(duì)于字母的判斷是沒(méi)有必要的,其實(shí)我們可以使用obj[key]這種形式,其實(shí)這是一種hash表,這樣做我們可以同時(shí)完成字母的去重,以及城市的分類,且看代碼

上面代碼可以一次性完成分組,可能有的人會(huì)說(shuō)這樣代碼的可讀性不好,其實(shí)如果使用這種高封裝的api熟練的時(shí)候,一樣就看出這段代碼的意思,同時(shí)有很多情況下,我們只關(guān)心輸入和輸出的情況下,這種代碼帶來(lái)的好處顯而易見(jiàn),因?yàn)槲覀儾⒉魂P(guān)心你實(shí)現(xiàn)的細(xì)節(jié),這有點(diǎn)函數(shù)式,函數(shù)式編程也是只關(guān)心輸入輸出,對(duì)于實(shí)現(xiàn)細(xì)節(jié)是隱藏的,如果想知道具體實(shí)現(xiàn),就看源碼。
當(dāng)然上面的代碼依然不是很通用,比如下次我們不想依據(jù)letter這個(gè)字段分組,我們可能要重寫(xiě)一遍代碼,然而對(duì)比代碼,可能只有細(xì)微的差別,這個(gè)時(shí)候我們可以再進(jìn)行封裝,實(shí)現(xiàn)一個(gè)lodash庫(kù)里面的groupBy,代碼如下

當(dāng)我們是在項(xiàng)目中引入這個(gè)庫(kù)的時(shí)候,我們可能只關(guān)心,傳入的列表數(shù)據(jù),以及得到的已經(jīng)分組過(guò)的數(shù)據(jù)是不是我們想要的,而并不關(guān)心庫(kù)內(nèi)部是如何實(shí)現(xiàn)分組的,并且我們可以定制我們的分組規(guī)則,而不耦合具體的某個(gè)字段,這樣的好處顯而易見(jiàn)看下執(zhí)行結(jié)果

可以看到上面的方法很靈活也很通用,當(dāng)然這有點(diǎn)“函數(shù)式”。這樣的結(jié)果其實(shí)我們完成分組只用了一行代碼,并且很通用,在以后的項(xiàng)目中什么時(shí)候可以使用這種高封裝的api呢?當(dāng)我們并不關(guān)心執(zhí)行過(guò)程,只關(guān)心結(jié)果的時(shí)候,我們可以封裝一些這種有點(diǎn)函數(shù)式的api。很通用,并且其實(shí)并沒(méi)有降低代碼的可讀性。