参考文章:面试官连环追问:数组拍平(扁平化) 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方法的关键思路

实现思路:

  • 循环数组里的每一个元素
  • 判断该元素是否为数组
    • 是数组的话,继续循环遍历这个元素——数组
    • 不是数组的话,把元素添加到新的数组中

实现流程:

  1. 创建一个空数组,用来保存遍历到的非数组元素
  2. 创建一个循环遍历数组的函数,cycleArray
  3. 取得数组中的每一项,验证Array.isArray()
  • 数组的话,继续循环
  • 非数组的话,添加到新数组中
  1. 返回新数组对象

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]

本文总结

看完这篇文章的同学,可以在面试的时候分类,分思想给面试官描述,可以先说我用哪几种思想实现过,它们的写法又分别有什么不同。

最后希望这篇文章可以帮助到大家,感谢阅读。

看完三件事❤

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

  1. 点赞,转发,有你们的 在看,才是我创造的动力。
  2. 关注公众号 前端时光屋,不定期分享原创知识。
  3. 同时可以期待后续文章ing?

es6删除数组某一项_精学手撕系列——数组扁平化相关推荐

  1. java二维数组杨辉三角_实验----Java的二维数组的应用及杨辉三角的编写

    (1) 编写一个程序,生成一个10*10的二维随机整数数组,并将该数组的每行最大值保存于一个一维数组中,将每列平均值保存于另外一个一维数组中并分别输出. (2) 编程输出杨辉三角的前10行. 找出一个 ...

  2. 二分法查找平方和_面试手撕系列:二分法

    最近春招开始了,面试面着面着一言不合就开始手撕代码手撕就手撕,接下来我打算写几个专题讲讲面试中手撕的常见题目 这些都是LeetCode上有的题目 手撕无非就是 树.链表.二分.字符串这些常用的数据结构 ...

  3. linux mint 图标主题_给小白的Linux Mint Xfce扁平化美化攻略

    提起轻量级桌面环境,不知大家回想起哪些?LXDE/LXQT.xfce4.mate亦或是其他小众软件呢?在这些桌面中,我对xfce情有独钟.这里面还确实是有过一段渊源,当初家中台式机(速龙240+英伟达 ...

  4. es6删除数组某一项_什么时候用集合,什么时候用数组?一文帮你清晰界定

    全文共3313字,预计学习时长10分钟 图源:Unsplash Set(集合)对象类型于2015年在ECMAScript*规范中提出,可以在 Node.js和大部分浏览器中使用. *ECMA是Euro ...

  5. es6删除数组某一项_「JavaScript 从入门到精通」10.数组

    往期回顾 「JavaScript 从入门到精通」1.语法和数据类型 「JavaScript 从入门到精通」2.流程控制和错误处理 「JavaScript 从入门到精通」3.循环和迭代 「JavaScr ...

  6. js提取数组某一项的属性值,组成新数组

    js提取数组某一属性值,将每一项的某个属性之,组成新数组. var arr = [{ id: 1, name: "张三" },{ id: 2, name: "李四&quo ...

  7. python定义数组是带指针_在cython中声明numpy数组和c指针

    在我的代码中,我通常使用numpy数组在方法和类之间进行接口.为了优化程序的核心部分,我使用cython和那些numpy数组的c指针.不幸的是,我目前声明数组的方式相当长.在 例如,假设我有一个方法, ...

  8. c判断char数组是否为空_你学过数组,那你知道柔性数组吗?

    1 引言 定长数组包 在平时的开发中,缓冲区数据收发时,如果采用缓冲区定长包,假定大小是 1k,MAX_LENGTH 为 1024.结构体如下: // 定长缓冲区struct max_buffer{ ...

  9. 基类数组存放派生类_永远不要将派生类数组赋值给基类类型指针

    C.152: Never assign a pointer to an array of derived class objects to a pointer to its base C.152:永远 ...

最新文章

  1. 软件开发环境-过程控制和消息服务器
  2. 洛谷P3960 列队(动态开节点线段树)
  3. boost::multi_array模块实现测试reshaping功能
  4. Java开发笔记(二十三)数组工具Arrays
  5. 条件控制与条件传送详解
  6. Ajax的XMLHttpRequest对象
  7. 常见笔顺错误的字_最全汉字笔顺正确写法,建议家长为孩子收藏
  8. echo -e “\033[字背景颜色 字体颜色m字符串\033[0m“解释
  9. ubuntu切换python版本
  10. 数据结构---堆的相关操作
  11. 《OpenGL超级宝典》 - 源代码文件
  12. 记一次进销存软件的破解
  13. java和是10的10次方的素数,10的11次方之内相邻两素数的最大差值
  14. 使用fail2ban解决暴力破解问题
  15. catia刨面命令_Catia查看装配体剖面的操作方法
  16. 高并发系统设计四(系统怎样做到高可用)
  17. Excel里关于if的9个函数,如何指定条件求和、计数、平均等
  18. 部署https证书的端口是什么意思
  19. 守护线程(Daemon)、钩子线程(Hook)简述
  20. 美赛18b题O奖论文学习(二)

热门文章

  1. linux 检测mysql链接_MySQL笔记
  2. python画一条水平直线(matplotlib)
  3. MATLAB报错Invalid ADAPTORNAME specified. Type 'imaqhwinfo' for a list of available ADAPTORNAMEs. Image
  4. Windows10安装TeXlive和TeXstudio
  5. 关于找工作和选专业的思考
  6. 一个sql生成hive日期维度表
  7. 22条API设计的实践
  8. Java并发编程实战~Lock
  9. 自定义ClassLoader
  10. C++学习之路 | PTA乙级—— 1004 成绩排名 (20分)(精简)