摘要:今天回答了的問(wèn)題生產(chǎn)嵌套數(shù)組也就是對(duì)數(shù)組分組更好的寫法。實(shí)現(xiàn)像這種,目標(biāo)數(shù)組長(zhǎng)度和原數(shù)組長(zhǎng)度不一致的情況,函數(shù)式寫法很容易想到函數(shù)。小結(jié)數(shù)組分組是一個(gè)很簡(jiǎn)單的問(wèn)題,有很多種方法來(lái)處理。
數(shù)據(jù)和參數(shù)和期望結(jié)果今天回答了 @_bleach 的問(wèn)題:JS生產(chǎn)嵌套數(shù)組(也就是對(duì)數(shù)組分組)更好的寫法?;卮鸬倪^(guò)程中對(duì) lodash _.chunk() 產(chǎn)生了好奇,所以分析了一下它的源碼,再加上我自己的解決方案,收集了如下一些方案,分享給大家
按慣例,我還是使用 es6 語(yǔ)法,在 Node7 中實(shí)驗(yàn)通過(guò)
const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; const groupByNum = 3;RxJS
因?yàn)樽罱趯W(xué)習(xí) RxJs,所以順手做了個(gè) RxJs 解決方案。但這不是重點(diǎn)。不了解或者很了解 RxJs 的請(qǐng)忽略。
RxJava 很火,其實(shí) ReactiveX 有很多種語(yǔ)言的實(shí)現(xiàn),JavaScript 的實(shí)例就是 RxJs,建議學(xué)習(xí)的同學(xué)直接上 5.0 Beta。不過(guò) RxJs 主要用于異步流處理,所以需要通過(guò)回調(diào)函數(shù)來(lái)使用結(jié)果。
const Rx = require("rxjs"); const out = Rx.Observable.from(data) .bufferCount(groupByNum) .toArray() .do((result) => { console.log(result) }) .subscribe();
上面的 do() 一句可以直接寫成 do(console.log),寫成現(xiàn)在這樣的目的是為了讓大家看到計(jì)算結(jié)果在哪。
_.chunk() 實(shí)現(xiàn)lodash 提供了大量數(shù)據(jù)處理的方法,_.chunk() 專為分組而生
const _ = require("lodash"); const result = _.chunk(data, groupByNum);_.chunk() 的源碼
在 node 環(huán)境也,通過(guò) npm 安裝 lodash 之后就能在 node_modules/lodash 目錄下找到源碼文件 chunk.js
npm install lodash
所以完整的源碼不貼了,只看下關(guān)鍵的那一句
while (index < length) { result[resIndex++] = baseSlice(array, index, (index += size)); }
baseSlice() 是 lodash 對(duì) Array.prototype.slice() 的兼容性實(shí)現(xiàn),可以直接當(dāng) slice() 來(lái)看。看了這個(gè)源碼,我有了函數(shù)式寫法的思路,后面通過(guò) slice() + map() 實(shí)現(xiàn)部分詳述。
reduce() 實(shí)現(xiàn)像這種,目標(biāo)數(shù)組長(zhǎng)度和原數(shù)組長(zhǎng)度不一致的情況,函數(shù)式寫法很容易想到 reduce() 函數(shù)。只可惜單純的 reduce() 做不出來(lái)(在 data.length 不能被 groupByNum 整除的時(shí)候)
function groupArray(data, cols) { const r = data.reduce((r, t) => { r.current.push(t); if (r.current.length === cols) { r.list.push(r.current); r.current = []; } return r; }, { list: [], current: [] }); if (r.current.length) { r.list.push(r.current); } return r.list; } const result = groupArray(data, groupByNum);
reduce() 的初始化對(duì)象是 { list: [], current: [] },其中 list 是要得計(jì)算出來(lái)的結(jié)果,而 current 是中間變量,用于生成每個(gè)組。
最后由于不有保證 data.length 一定被 groupByNum 整除,所以可能會(huì)有一個(gè)未完成的 current 沒(méi)被 push 到 list 當(dāng)中,所以專門進(jìn)行了一個(gè)判斷和處理。因此不能寫成函數(shù)式寫法,有些遺憾。
forEach() 實(shí)現(xiàn)既然不能用函數(shù)式寫法,那 forEach() 或者 for ... of 實(shí)現(xiàn)就會(huì)更容易理解一些。
function groupArray(data, cols) { const list = []; let current = []; // for (t of data) { data.forEach(t => { current.push(t); if (current.length === cols) { list.push(current); current = []; } }); // } // for (t of data) if (current.length) { list.push(current); } return list; }slice() + map() 實(shí)現(xiàn)
看到了 _.chunk() 的源碼,讓我產(chǎn)生了函數(shù)式寫法的靈感,相比上面的解決方案,更難于理解,不過(guò)語(yǔ)法看起來(lái)很酷
const result = Array.apply(null, { length: Math.ceil(data.length / groupByNum) }).map((x, i) => { return data.slice(i * groupByNum, (i + 1) * groupByNum); });
Array.apply() 是為了生成一個(gè)長(zhǎng)度為 Math.ceil(data.length / groupByNum) 的數(shù)組作為 map() 的源,map() 不需要這個(gè)源的數(shù)據(jù),只需要這個(gè)源每個(gè)數(shù)組的 index。
Math.ceil() 用于保證在除法計(jì)算有余數(shù)的時(shí)候?qū)ι?+1,即循環(huán)次數(shù) +1。
然后在算得的循環(huán)次數(shù)中,通過(guò) slice 返回每一段結(jié)果,通過(guò) map() 映射出來(lái),最終生成需要的結(jié)果。
小結(jié)數(shù)組分組是一個(gè)很簡(jiǎn)單的問(wèn)題,有很多種方法來(lái)處理。本文并不是想告訴大家如何處理這個(gè)問(wèn)題,而是將我處理問(wèn)題的思路分享出來(lái),希望能對(duì)處理各種數(shù)據(jù)問(wèn)題帶來(lái)一點(diǎn)點(diǎn)啟發(fā)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/80868.html
摘要:實(shí)現(xiàn)數(shù)組更多的高階函數(shù)吾輩的博客原文場(chǎng)景雖說(shuō)人人平等,但有些人更加平等。若是有一篇適合萌新閱讀的自己實(shí)現(xiàn)數(shù)組更多操作的文章,情況或許會(huì)發(fā)生一些變化。類似于的初始值,但它是一個(gè)函數(shù),避免初始值在所有分組中進(jìn)行累加。 JavaScript 實(shí)現(xiàn)數(shù)組更多的高階函數(shù) 吾輩的博客原文: https://blog.rxliuli.com/p/fc... 場(chǎng)景 雖說(shuō)人人平等,但有些人更加平等。 為...
摘要:序列化為字符串之后它的各個(gè)屬性已經(jīng)被解除了引用,重新相當(dāng)于創(chuàng)建了一個(gè)新的對(duì)象。類似于的,的命令行終端。基本思路函數(shù)的使用以及協(xié)議。 多行注釋的陷阱 由于正則表達(dá)式字面量的存在,多行注釋可能會(huì)產(chǎn)生陷阱,例如以下程序?qū)伋鲥e(cuò)誤: /* var a = /h*/.test(hello); */ 正則結(jié)束前的那個(gè)星號(hào)將被解析為注釋結(jié)束符,從而.被認(rèn)為是不合法的.所以盡量避免使用多行注釋 整型 ...
摘要:排序加了的插入排序。分別以索引數(shù)為的元素為起點(diǎn),將其看做不同的組,,,為一組,,為一組依次分組,按照組為單位進(jìn)行插入排序。各組都已經(jīng)插入排序一輪過(guò)后,將除以向下取整,再進(jìn)行分組并將各組分別進(jìn)行插入排序,直到為。 1.冒泡排序: 比較相鄰的兩個(gè)數(shù),如果前一個(gè)數(shù)大于后一個(gè)數(shù),就將這兩個(gè)數(shù)換位置。每一次遍歷都會(huì)將本次遍歷最大的數(shù)冒泡到最后。為了將n個(gè)數(shù)排好序,需要n-1次遍歷。 如果某次遍歷...
摘要:早已實(shí)現(xiàn)了正則命名分組提案,只是我們很少使用,本文將介紹的正則命名分組。所有這些問(wèn)題,都可以通過(guò)正則命名分組來(lái)解決。該名稱必須是合法的標(biāo)識(shí)符。 前言 以往我們只是習(xí)慣于通過(guò)數(shù)組下標(biāo)來(lái)訪問(wèn)正則匹配到的分組,但分組達(dá)到4、5個(gè)時(shí),標(biāo)識(shí)起來(lái)就會(huì)非常麻煩。V8早已實(shí)現(xiàn)了正則命名分組提案,只是我們很少使用,本文將介紹JS的正則命名分組。 以往的做法 假設(shè)要使用正則匹配一個(gè)日期的年月日,以往我們會(huì)...
摘要:玩轉(zhuǎn)對(duì)象中的正則表達(dá)式的正則表達(dá)式語(yǔ)法極大地借鑒了另一種腳本語(yǔ)言的正則表達(dá)式語(yǔ)法對(duì)象是的一個(gè)內(nèi)置對(duì)象,與,類似。創(chuàng)建對(duì)象可通過(guò)構(gòu)造函數(shù)創(chuàng)建。當(dāng)要根據(jù)用戶輸入來(lái)構(gòu)造正則表達(dá)式時(shí),必須采用構(gòu)造函數(shù)方式。如與被看做相同的字符模式。 玩轉(zhuǎn)javascript RegExp對(duì)象 js中的正則表達(dá)式 js的正則表達(dá)式語(yǔ)法極大地借鑒了另一種腳本語(yǔ)言Perl的正則表達(dá)式語(yǔ)法.RegExp對(duì)象是js的一...
閱讀 1978·2021-09-23 11:21
閱讀 1750·2019-08-29 17:27
閱讀 1113·2019-08-29 17:03
閱讀 787·2019-08-29 15:07
閱讀 2002·2019-08-29 11:13
閱讀 2435·2019-08-26 12:14
閱讀 1005·2019-08-26 11:52
閱讀 1780·2019-08-23 17:09