es6删除数组某一项_精学手撕系列——数组扁平化
参考文章:面试官连环追问:数组拍平(扁平化) flat 方法实现
编者荐语:
在前端面试中,手写flat
是非常基础的面试题,通常出现在笔试或者第一轮面试中,主要考察面试者基本的手写代码能力和JavaScript
的基本功。
今天就带大家从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 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 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]
本文总结
看完这篇文章的同学,可以在面试的时候分类,分思想给面试官描述,可以先说我用哪几种思想实现过,它们的写法又分别有什么不同。
最后希望这篇文章可以帮助到大家,感谢阅读。
看完三件事❤
如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的
在看
,才是我创造的动力。 - 关注公众号
前端时光屋
,不定期分享原创知识。 - 同时可以期待后续文章ing?
es6删除数组某一项_精学手撕系列——数组扁平化相关推荐
- java二维数组杨辉三角_实验----Java的二维数组的应用及杨辉三角的编写
(1) 编写一个程序,生成一个10*10的二维随机整数数组,并将该数组的每行最大值保存于一个一维数组中,将每列平均值保存于另外一个一维数组中并分别输出. (2) 编程输出杨辉三角的前10行. 找出一个 ...
- 二分法查找平方和_面试手撕系列:二分法
最近春招开始了,面试面着面着一言不合就开始手撕代码手撕就手撕,接下来我打算写几个专题讲讲面试中手撕的常见题目 这些都是LeetCode上有的题目 手撕无非就是 树.链表.二分.字符串这些常用的数据结构 ...
- linux mint 图标主题_给小白的Linux Mint Xfce扁平化美化攻略
提起轻量级桌面环境,不知大家回想起哪些?LXDE/LXQT.xfce4.mate亦或是其他小众软件呢?在这些桌面中,我对xfce情有独钟.这里面还确实是有过一段渊源,当初家中台式机(速龙240+英伟达 ...
- es6删除数组某一项_什么时候用集合,什么时候用数组?一文帮你清晰界定
全文共3313字,预计学习时长10分钟 图源:Unsplash Set(集合)对象类型于2015年在ECMAScript*规范中提出,可以在 Node.js和大部分浏览器中使用. *ECMA是Euro ...
- es6删除数组某一项_「JavaScript 从入门到精通」10.数组
往期回顾 「JavaScript 从入门到精通」1.语法和数据类型 「JavaScript 从入门到精通」2.流程控制和错误处理 「JavaScript 从入门到精通」3.循环和迭代 「JavaScr ...
- js提取数组某一项的属性值,组成新数组
js提取数组某一属性值,将每一项的某个属性之,组成新数组. var arr = [{ id: 1, name: "张三" },{ id: 2, name: "李四&quo ...
- python定义数组是带指针_在cython中声明numpy数组和c指针
在我的代码中,我通常使用numpy数组在方法和类之间进行接口.为了优化程序的核心部分,我使用cython和那些numpy数组的c指针.不幸的是,我目前声明数组的方式相当长.在 例如,假设我有一个方法, ...
- c判断char数组是否为空_你学过数组,那你知道柔性数组吗?
1 引言 定长数组包 在平时的开发中,缓冲区数据收发时,如果采用缓冲区定长包,假定大小是 1k,MAX_LENGTH 为 1024.结构体如下: // 定长缓冲区struct max_buffer{ ...
- 基类数组存放派生类_永远不要将派生类数组赋值给基类类型指针
C.152: Never assign a pointer to an array of derived class objects to a pointer to its base C.152:永远 ...
最新文章
- 软件开发环境-过程控制和消息服务器
- 洛谷P3960 列队(动态开节点线段树)
- boost::multi_array模块实现测试reshaping功能
- Java开发笔记(二十三)数组工具Arrays
- 条件控制与条件传送详解
- Ajax的XMLHttpRequest对象
- 常见笔顺错误的字_最全汉字笔顺正确写法,建议家长为孩子收藏
- echo -e “\033[字背景颜色 字体颜色m字符串\033[0m“解释
- ubuntu切换python版本
- 数据结构---堆的相关操作
- 《OpenGL超级宝典》 - 源代码文件
- 记一次进销存软件的破解
- java和是10的10次方的素数,10的11次方之内相邻两素数的最大差值
- 使用fail2ban解决暴力破解问题
- catia刨面命令_Catia查看装配体剖面的操作方法
- 高并发系统设计四(系统怎样做到高可用)
- Excel里关于if的9个函数,如何指定条件求和、计数、平均等
- 部署https证书的端口是什么意思
- 守护线程(Daemon)、钩子线程(Hook)简述
- 美赛18b题O奖论文学习(二)
热门文章
- linux 检测mysql链接_MySQL笔记
- python画一条水平直线(matplotlib)
- MATLAB报错Invalid ADAPTORNAME specified. Type 'imaqhwinfo' for a list of available ADAPTORNAMEs. Image
- Windows10安装TeXlive和TeXstudio
- 关于找工作和选专业的思考
- 一个sql生成hive日期维度表
- 22条API设计的实践
- Java并发编程实战~Lock
- 自定义ClassLoader
- C++学习之路 | PTA乙级—— 1004 成绩排名 (20分)(精简)