当前位置: 首页 > 科技观察

精雪手撕系列——数组扁平化

时间:2023-03-21 21:07:25 科技观察

今天带大家从0了解扁平化的特性到手写实现扁平化,再到连环问答中重新学习扁平化数组Array.prototype.flat的方法面试官()一段代码总结了Array.prototype.flat()的特点注:数组扁平化方法Array.prototype.flat()也叫数组扁平化、数组扁平化、数组降维。letarr=[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]]]];letarr2=[12,23,[34,56,,]]console.log(arr.flat());//[12,23,34,56]Array.prototype.flat()特性总结Array.prototype.flat()用于“压平”嵌套数组,成一个一维数组。此方法返回一个新数组,对原始数据没有影响。不传参数时,默认“展平”一层,可以传入一个整数表示“展平”的层数。传递<=0的整数将返回原始数组。当Infinity关键字不作为参数“扁平化”时,无论嵌套多少层,都会被转换成一维数组。如果原数组有空位,Array.prototype.flat()会跳过空位。面试官连续N个问题:第一个问题:下面的数组如何展平?letarr=[[1,2,2],[3,4,5,5],[6,7,8,9,[11,12,[12,13,[14]]]],10];小伙伴们首先想到的是使用ES6的Array.prototype.flat方法。方法一:flatarr=arr.flat(2);//[1,2,2,3,4,5,5,6,7,8,9,11,12,[12,13,[14]],10]flat中传入number时,就是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参数来帮助我们全部展开。第二个问题:还有别的办法吗?因为它们与高版本浏览器不兼容。方法二:转成字符串,再用字符串对象转成数组。可以先将多维数组转为字符串,然后将字符串对象拆分为String数组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)while(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实现扁平化方法letarr=[[1,2,2],[3,4,5,5],[6,7,8,9,[11,12,[12,13,[14]]]],10];functionmyFlat(){_this=this;//保存这个:arrletnewArr=[];//循环arr中的每一项,将不是数组的元素存入newArrletcycleArray=(arr)=>{for(leti=0;i{letnewArr=[];letcycleArray=(arr)=>{for(leti=0;i{returnarr.reduce((pre,cur)=>{returnpre.concat(cur);},[]);};console.log(myFlat(arr));//[12,23,34,56,[78,90,100,[110,120,130,140]]]constmyFlat=arr=>{returnarr.reduce((pre,cur)=>{returnpre.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)其实就像遍历数组一样item,看是否是数组元素,如果是,继续递归遍历,如果不是,则直接数字组合不是数组元素第五题:用栈的思想实现平面函数栈的思路:最后-in-first-out数据结构获取并删除栈中最后一个元素A,判断A是否为数组元素,直到栈中元素为空,将所有元素添加到newArr为数组,然后push到入栈,不断循环栈中的元素,直到栈为空且不是数组,然后unshift加入newArr//入栈思路functionflat(arr){constnewArr=[];conststack=[].concat(arr);//将数组元素复制到栈中,直接赋值会改变原数组//如果栈不为空,循环遍历while(stack.length!==0){constval=stack.pop();//删除数组的最后一个元素并获取if(Array.isArray(val)){stack.push(...val);//如果数组再次入栈,又展开一层}别的{newArr.unshift(val);//如果不是数组,取出来放入结果数组}}returnnewArr;}letarr=[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]这篇文章综上所述,看过这篇文章的同学可以在面试的时候把自己的想法分类描述给面试官。你可以先说说我是用了哪些思路来实现的,怎么写的不一样。