您现在的位置是:亿华云 > IT科技类资讯
精学手撕系列——数组扁平化
亿华云2025-10-02 19:00:35【IT科技类资讯】7人已围观
简介今天就带大家从0了解flat特性到手写实现flat,再到接住面试官的连环追问中重新学习一遍数组扁平化flat方法Array.prototype.flat()一段代码总结Array.prototype.
今天就带大家从0了解flat特性到手写实现flat,精学再到接住面试官的手撕数组连环追问中重新学习一遍数组扁平化flat方法
Array.prototype.flat()一段代码总结Array.prototype.flat()特性
注:数组拍平方法 Array.prototype.flat() 也叫数组扁平化、数组拉平、系列数组降维。扁平
let arr = [12,精学 23, [34, 56, [78, 90, 100, [110, 120, 130]]]]; console.log(arr.flat()); // [ 12, 23, 34, 56, [ 78, 90, 100, [ 110, 120, 130 ] ] ] console.log(arr.flat(2)); // [ 12, 23, 34, 56, 78, 90, 100, [ 110, 120, 130 ] ] console.log(arr.flat(Infinity)); // [12, 23, 34, 56, 78, 90, 100, 110, 120, 130] console.log(arr.flat(0)); // [12, 23, [34, 56, [78, 90, 100, [110, 120, 130]]]]; console.log(arr.flat(-10)); // [12, 23, [34, 56, [78, 90, 100, [110, 120, 130]]]]; let arr2 = [12, 23, [34, 56, ,]] console.log(arr.flat()); // [ 12, 23, 34, 56 ]Array.prototype.flat() 特性总结
Array.prototype.flat() 用于将嵌套的数组“拉平”,变成一维的手撕数组数组。该方法返回一个新数组,系列对原数据没有影响。扁平
不传参数时,精学默认“拉平”一层,手撕数组可以传入一个整数,系列表示想要“拉平”的扁平层数。
传入 <=0 的精学整数将返回原数组,不“拉平”
Infinity 关键字作为参数时,手撕数组无论多少层嵌套,系列都会转为一维数组
如果原数组有空位,Array.prototype.flat() 会跳过空位。
面试官 N 连问:第一问:下面数组如何实现扁平化?
let arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10 ];小伙伴首先想到的肯定是用 ES6 的Array.prototype.flat方法呀
方法一:flat
arr = arr.flat(2); // [ 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, [ 12, 13, [ 14 ] ], 10 ]当flat中传入数字时,是扁平对应的层数,显然这不是我们想要的,因为它还没有完全展开。
这是高防服务器,flat函数中就为我们提供了一个参数Infinity,译为无穷的意思。
arr = arr.flat(Infinity); /* [ 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10 ] */当我们不知道数组中嵌套了几维数组时,我们可以用Infinity这个参数,帮我们全部展开。
第二问:还有其它的办法吗?因为它们在高版本浏览器并不兼容
方法二:转换为字符串,再把字符串对象用,转换成数组
可以先把多维数组先转换为字符串,再基于,分隔符将字符串对象分割成字符串数组toString() 扁平化数组
arr = arr.toString(); // "1,2,2,3,4,5,5,6,7,8,9,11,12,12,13,14,10" arr = arr.toString().split(,); // ["1", "2", "2", "3", "4", "5", "5", "6", "7", "8", "9", "11", "12", "12", "13", "14", "10"] arr = arr.toString().split(,).map(item => parseFloat(item)); // [1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]除了上面的方法还有什么方法转换为字符串呢?
JSON.stringify()扁平化数组
arr = JSON.stringify(arr); // "[[1,2,2],[3,4,5,5],[6,7,8,9,[11,12,[12,13,[14]]]],10]" arr = JSON.stringify(arr).replace(/(\[|\])/g, ); // "1,2,2,3,4,5,5,6,7,8,9,11,12,12,13,14,10" arr = JSON.stringify(arr).replace(/(\[|\])/g, ).split(,).map(item=>parseFloat(item)); // [1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]方法三:循环验证是否为数组基于数组的some方法,只要数组里面有一项元素是数组就继续循环,扁平数组
核心:[].concat(...arr)
whilte (arr.some(item => Array.isArray(item))) { arr = [].concat(...arr); } console.log(arr); // [1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]第三问:能自己实现一个 flat 扁平化吗?
先回答:能!!再跟着我分析思路:如何实现呢,其实思路非常简单:在数组中找到是数组类型的元素,然后将他们展开,这就是flat方法的关键思路
实现思路:
循环数组里的每一个元素
判断该元素是否为数组
是数组的话,继续循环遍历这个元素——数组
不是数组的亿华云计算话,把元素添加到新的数组中
实现流程:创建一个空数组,用来保存遍历到的非数组元素
创建一个循环遍历数组的函数,cycleArray
取得数组中的每一项,验证Array.isArray()
数组的话,继续循环
非数组的话,添加到新数组中
返回新数组对象
ES5 实现 flat 扁平化方法let arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10 ]; function myFlat() { _this = this; // 保存 this:arr let newArr = []; // 循环arr中的每一项,把不是数组的元素存储到 newArr中 let cycleArray = (arr) => { for (let i=0; i< arr.length; i++) { let item = arr[i]; if (Array.isArray(item)) { // 元素是数组的话,继续循环遍历该数组 cycleArray(item); continue; } else{ newArr.push(item); // 不是数组的话,直接添加到新数组中 } } } cycleArray(_this); // 循环数组里的每个元素 return newArr; // 返回新的数组对象 } Array.prototype.myFlat = myFlat; arr = arr.myFlat(); // [1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]ES6 实现 flat 扁平化方法
const myFlat = (arr) => { let newArr = []; let cycleArray = (arr) => { for(let i = 0; i < arr.length; i++) { let item = arr[i]; if (Array.isArray(item)) { cycleArray(item); continue; } else { newArr.push(item); } } } cycleArray(arr); return newArr; } myFlat(arr); // [1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]第四问:请使用reduce实现flat函数相信很多面试官都会指定让面试者用reduce方法实现flat函数
其实思路也是一样的,在实现之前,先来看一下
它的核心:[].concat(...arr)
但是它只能将数组元素展开一层,来看下面例子:
let arr2 = [12, 23, [34, 56, [78, 90, 100]]]; [].concat(...arr2); // [ 12, 23, 34, 56, [ 78, 90, 100 ] ]细心的同学可以发现[].concat(...arr)只能展开一层数组元素,香港云服务器当有更深层次的,是无法展开的
接下来,我们来看看用reduce怎么实现?
let arr = [12, 23, [34, 56, [78, 90, 100, [110, 120, 130, 140]]]]; const myFlat = arr => { return arr.reduce((pre, cur) => { return pre.concat(cur); }, []); }; console.log(myFlat(arr)); // [ 12, 23, 34, 56, [ 78, 90, 100, [ 110, 120, 130, 140 ] ] ] const myFlat = arr => { return arr.reduce((pre, cur) => { return pre.concat(Array.isArray(cur) ? myFlat(cur) : cur); }, []); }; console.log(myFlat(arr)); // [12, 23, 34, 56, 78, 90, 100, 110, 120, 130, 140]上面代码中的Array.isArray(cur)和myFlat(cur)实际就好比与遍历数组每一项,看它是不是数组元素,
如果是的话,则继续递归遍历,不是的话直接数组合并非数组元素。
第五问:使用栈的思想实现flat函数栈思想: 后进先出的数据结构
实现思路:
不断获取并删除栈中最后一个元素A,判断A是否为数组元素,直到栈内元素为空,全部添加到newArr
是数组,则push到栈中,继续循环栈内元素,直到栈为空
不是数组,则unshift添加到newArr中 // 栈思想 function flat(arr) { const newArr = []; const stack = [].concat(arr); // 将数组元素拷贝至栈,直接赋值会改变原数组 //如果栈不为空,则循环遍历 while (stack.length !== 0) { const val = stack.pop(); // 删除数组最后一个元素,并获取它 if (Array.isArray(val)) { stack.push(...val); // 如果是数组再次入栈,并且展开了一层 } else { newArr.unshift(val); // 如果不是数组就将其取出来放入结果数组中 } } return newArr; } let arr = [12, 23, [34, 56, [78, 90, 100, [110, 120, 130, 140]]]]; console.log(flat(arr)); // [12, 23, 34, 56, 78, 90, 100, 110, 120, 130, 140]本文总结看完这篇文章的同学,可以在面试的时候分类,分思想给面试官描述,可以先说我用哪几种思想实现过,它们的写法又分别有什么不同。
很赞哦!(9)