扁平化
數(shù)組的扁平化,就是將一個(gè)嵌套多層的數(shù)組 array (嵌套可以是任何層數(shù))轉(zhuǎn)換為只有一層的數(shù)組。
舉個(gè)例子,假設(shè)有個(gè)名為 flatten 的函數(shù)可以做到數(shù)組扁平化,效果就會(huì)如下:
var arr = [1, [2, [3, 4]]];console.log(flatten(arr)) // [1, 2, 3, 4]
知道了效果是什么樣的了,我們可以去嘗試著寫(xiě)這個(gè) flatten 函數(shù)了
遞歸
我們最一開(kāi)始能想到的莫過(guò)于循環(huán)數(shù)組元素,如果還是一個(gè)數(shù)組,就遞歸調(diào)用該方法:
// 方法 1var arr = [1, [2, [3, 4]]];function flatten(arr) {var result = [];for (var i = 0, len = arr.length; i < len; i++) {if (Array.isArray(arr[i])) {result = result.concat(flatten(arr[i]))}else {result.push(arr[i])}}return result;}console.log(flatten(arr))toString
如果數(shù)組的元素都是數(shù)字,那么我們可以考慮使用 toString 方法,因?yàn)椋?/p>
[1, [2, [3, 4]]].toString() // "1,2,3,4"
調(diào)用 toString 方法,返回了一個(gè)逗號(hào)分隔的扁平的字符串,這時(shí)候我們?cè)?split,然后轉(zhuǎn)成數(shù)字不就可以實(shí)現(xiàn)扁平化了嗎?
// 方法2var arr = [1, [2, [3, 4]]];function flatten(arr) {return arr.toString().split(',').map(function(item){return +item})}console.log(flatten(arr))然而這種方法使用的場(chǎng)景卻非常有限,如果數(shù)組是 [1, '1', 2, '2'] 的話(huà),這種方法就會(huì)產(chǎn)生錯(cuò)誤的結(jié)果。
reduce
既然是對(duì)數(shù)組進(jìn)行處理,最終返回一個(gè)值,我們就可以考慮使用 reduce 來(lái)簡(jiǎn)化代碼:
// 方法3var arr = [1, [2, [3, 4]]];function flatten(arr) {return arr.reduce(function(prev, next){return prev.concat(Array.isArray(next) ? flatten(next) : next)}, [])}console.log(flatten(arr))ES6 增加了擴(kuò)展運(yùn)算符,用于取出參數(shù)對(duì)象的所有可遍歷屬性,拷貝到當(dāng)前對(duì)象之中:
var arr = [1, [2, [3, 4]]];console.log([].concat(...arr)); // [1, 2, [3, 4]]
我們用這種方法只可以扁平一層,但是順著這個(gè)方法一直思考,我們可以寫(xiě)出這樣的方法:
// 方法4var arr = [1, [2, [3, 4]]];function flatten(arr) {while (arr.some(item => Array.isArray(item))) {arr = [].concat(...arr);}return arr;}console.log(flatten(arr))undercore
那么如何寫(xiě)一個(gè)抽象的扁平函數(shù),來(lái)方便我們的開(kāi)發(fā)呢,所有又到了我們抄襲 underscore 的時(shí)候了~
在這里直接給出源碼和注釋?zhuān)且⒁猓@里的 flatten 函數(shù)并不是最終的 _.flatten,為了方便多個(gè) API 進(jìn)行調(diào)用,這里對(duì)扁平進(jìn)行了更多的配置。
/*** 數(shù)組扁平化* @param {Array} input 要處理的數(shù)組* @param {boolean} shallow 是否只扁平一層* @param {boolean} strict 是否嚴(yán)格處理元素,下面有解釋* @param {Array} output 這是為了方便遞歸而傳遞的參數(shù)* 源碼地址:https://github.com/jashkenas/underscore/blob/master/underscore.js#L528*/function flatten(input, shallow, strict, output) {// 遞歸使用的時(shí)候會(huì)用到outputoutput = output || [];var idx = output.length;for (var i = 0, len = input.length; i < len; i++) {var value = input[i];// 如果是數(shù)組,就進(jìn)行處理if (Array.isArray(value)) {// 如果是只扁平一層,遍歷該數(shù)組,依此填入 outputif (shallow) {var j = 0, len = value.length;while (j < len) output[idx++] = value[j++];}// 如果是全部扁平就遞歸,傳入已經(jīng)處理的 output,遞歸中接著處理 outputelse {flatten(value, shallow, strict, output);idx = output.length;}}// 不是數(shù)組,根據(jù) strict 的值判斷是跳過(guò)不處理還是放入 outputelse if (!strict){output[idx++] = value;}}return output;}
|
新聞熱點(diǎn)
疑難解答
圖片精選