Javascript基础:老生常谈之数组扁平化
分类:javascript
首先是解释概念,什么是数组扁平化?
我们在平时开发过程中总可能会遇到数组嵌套数组,但是我们希望得到的数据是一个保持原有先后顺序的一维数组,所以数组扁平化这个想法应运而生。
// 这是一个多层嵌套的数组,假设有一个完美的数据扁平化方法_flat
const arr = [1, [3, 4], [7, [1, [9]]]]
console.log(_flat(arr)) // [1, 3, 4, 7, 1, 9]
接下来我们就来尝试使用各种方法来实现这个_flat。基本上是我能想到的最全的方法了。
-
普通递归
这个思路其实比较容易理解,也是大家最容易想到的方法之一。首先我们去遍历一个数组,如果碰到有元素是数组,那么对该元素进行更深层的遍历。
// 这里写的尽量避免使用了ES6 function _flat(oriArr) { let results = [] for (let i = 0; i < oriArr.length; i++) { if (Object.prototype.toString.call(oriArr[i]) === '[object Array]') { results = results.concat(_flat(oriArr[i])) } else { results.push(oriArr[i]) } } return results }
-
使用reduce函数
这一种其实是对第一种方法的一个简化或美化,使用reduce去代替for循环同时又节约了一个新变量
function _flat(oriArr) { return oriArr.reduce(function (total, currentValue) { return total.concat(Object.prototype.toString.call(currentValue) === '[object Array]' ? _flat(currentValue) : currentValue) }, []) }
-
ES6的扩展运算符
function _flat(oriArr) { while (oriArr.some(item => Array.isArray(item))) { oriArr = [].concat(...oriArr) } return oriArr }
看完上面的写法是不是突然感觉有一些疑惑和不自然?感觉扩展运算符好像跟自己理解地不太一样了,其实究其原因是因为对concat函数理解地不够透彻而已。用下面几个例子来说明
// concat接收若干个参数,如果参数是非数组,那么会直接将它作为数组元素加入新数组 // 如果参数是一个数组,那么会使用该数组的元素来作为来作为新数组的元素 console.log([].concat(1, [2, 3])) // [1, 2, 3] console.log([].concat([1, 2], [3, 4])) // [1, 2, 3, 4] console.log([].concat(1, [2, [3, 4]])) // [1, 2, [3, 4]] console.log([].concat([1, [2, [3, 4]]])) // [1, [2, [3, 4]]] [].concat(...[1, [2, [3, 4]]]) === [].concat(1, [2, [3, 4]])
-
通过与字符串类型的相互转换
function _flat(oriArr) { // toString会将数组直接拉平成字符串,如 [1, [2, 3, [4, 5]]].toString() === '1,2,3,4,5' // 然后通过split将其转换为数组 // 或者可以使用join代替toString,如oriArr.join(',').split(',') return oriArr.toString().split(',') }
-
ES6 flat
对于这个方法其实很多人只知道不填的时候默认只拉平一层数组,填数组进去只拉平小于等于该数字的层级,但是其实它还可以用Infinity作为参数
function _flat(oriArr) { return oriArr.flat(Infinity) }
-
正则与JSON方法
function _flat(oriArr) { let str = JSON.stringify(oriArr) str = str.replace(/(\[|\])/g, '') str = '[' + str + ']' return JSON.parse(str) }
对正则不太理解的同学可以多看看语法,这里也推荐一个正则脑图的展示网站regexper.com/
总结
以上就是我能想到的6种数组扁平化的方法,其中4和6都进行了类型转换,那么这两种方法在特殊情况下势必会有一些问题,如数组中含有特殊符号,或者是数组中如果是数字,而最终返回的元素可能会变成字符串,都需要做一下特殊情况处理。
最后,望自己好好加油,不要再做咸鱼了~
作者:掘金-Javascript基础:老生常谈之数组扁平化