JavaScript篇:数组扁平化:从‘千层饼’到‘一马平川’的六种神操作 🥞→📜

大家好,我是江城开朗的豌豆,一名拥有6年以上前端开发经验的工程师。我精通HTML、CSS、JavaScript等基础前端技术,并深入掌握Vue、React、Uniapp、Flutter等主流框架,能够高效解决各类前端开发问题。在我的技术栈中,除了常见的前端开发技术,我还擅长3D开发,熟练使用Three.js进行3D图形绘制,并在虚拟现实与数字孪生技术上积累了丰富的经验,特别是在虚幻引擎开发方面,有着深入的理解和实践。

我一直认为技术的不断探索和实践是进步的源泉,近年来,我深入研究大数据算法的应用与发展,尤其在数据可视化和交互体验方面,取得了显著的成果。我也注重与团队的合作,能够有效地推动项目的进展和优化开发流程。现在,我担任全栈工程师,拥有CSDN博客专家认证及阿里云专家博主称号,希望通过分享我的技术心得与经验,帮助更多人提升自己的技术水平,成为更优秀的开发者。

技术qq交流群:906392632

大家好,我是小杨,做了6年前端。今天要聊一个看似简单却让无数新手抓狂的话题------数组扁平化 。还记得我第一次面试时被问到"如何拍平多维数组",当场表演了"用递归递归递归..."的卡带现场,现在想起来脚趾还能抠出三室一厅 😅。今天就把这些年的经验总结成六大必杀技,保你看完直呼:"原来还能这么玩!"


一、生活场景:什么叫"数组不扁平"?

想象你收拾衣柜:

  • 千层饼数组[袜子, [裤子, [上衣, 腰带]], 鞋子](找双袜子要翻三层)
  • 扁平数组[袜子, 裤子,上衣,腰带,鞋子](一目了然)

需求:把嵌套数组变成一维数组,就是扁平化!


二、青铜选手:flat()方法(ES10真香)

javascript 复制代码
const messyCloset = ['袜子', ['裤子', ['上衣', '腰带']], '鞋子'];

// 1. 默认只拍平一层
const level1 = messyCloset.flat(); 
// ['袜子', '裤子', ['上衣', '腰带'], '鞋子']

// 2. 传入Infinity直接全平
const allFlat = messyCloset.flat(Infinity);
// ['袜子', '裤子', '上衣', '腰带', '鞋子']

我的翻车史

曾经以为flat(2)flat(Infinity)效果一样,直到遇到五层嵌套数组...


三、白银选手:reduce+递归(经典永流传)

javascript 复制代码
function flatten(arr) {
  return arr.reduce((result, item) => {
    return result.concat(
      Array.isArray(item) ? flatten(item) : item
    );
  }, []);
}

const myCloset = ['👖', ['👔', ['🧦']], '👟'];
console.log(flatten(myCloset)); // ['👖', '👔', '🧦', '👟']

适用场景

  • 需要兼容老浏览器时
  • 面试官盯着你手写实现时 😏

四、黄金选手:toString妙用(数字数组专属)

javascript 复制代码
const numLayers = [1, [2, [3, [4]]]];

// 1. 转字符串再分割
const strFlat = numLayers.toString().split(','); 
// ['1', '2', '3', '4']

// 2. 转数字(需处理非数字项)
const numFlat = strFlat.map(Number); 
// [1, 2, 3, 4]

致命缺陷

  • 会把[1, 'a']变成['1', 'a']
  • 遇到null, undefined直接转字符串

五、铂金选手:生成器函数(优雅处理海量数据)

javascript 复制代码
function* flattenGen(arr) {
  for (const item of arr) {
    Array.isArray(item) ? yield* flattenGen(item) : yield item;
  }
}

const hugeArray = [1, [2, [3, [4, ...[1000000个项]]]];
const flattened = [...flattenGen(hugeArray)]; // 按需生成不爆内存

性能优势

处理超大规模数组时,不会一次性占用大量内存


六、钻石选手:栈结构迭代(避免递归爆栈)

javascript 复制代码
function flattenStack(arr) {
  const stack = [...arr];
  const result = [];
  
  while (stack.length) {
    const next = stack.pop();
    Array.isArray(next) ? stack.push(...next) : result.push(next);
  }
  
  return result.reverse();
}

const deepArray = [1, [2, [3, [4]]];
console.log(flattenStack(deepArray)); // [1, 2, 3, 4]

适用场景

  • 嵌套层级极深时(递归可能栈溢出)
  • 需要控制遍历顺序时

七、王者选手:Array.prototype.flatMap (ES2019)

javascript 复制代码
// 先map再flat(1)的语法糖
const data = [1, [2], 3];
const processed = data.flatMap(item => 
  Array.isArray(item) ? item : [item * 2]
);
// [2, 2, 6] 

神技巧

flatMap实现过滤+展开二合一:

javascript 复制代码
const mixed = [1, 2, , , 5];
const compact = mixed.flatMap(x => x || []);
// [1, 2, 5] (自动跳过空值)

八、终极选择指南

场景 推荐方案 原因
现代浏览器环境 flat(Infinity) 原生API性能最佳
需要兼容IE reduce+递归 兼容性好
纯数字数组 toString+split 取巧但高效
超大数据量 生成器函数 内存友好
需要控制遍历顺序 栈结构迭代 避免递归爆栈
需要边处理边展开 flatMap 代码最简洁

九、真实案例:树形菜单扁平化

javascript 复制代码
// 原始树形数据
const menuTree = [
  {
    name: '文件',
    children: [
      { name: '新建' },
      { name: '打开', children: [{ name: '从云端' }] }
    ]
  }
];

// 递归提取所有节点名
function getAllNames(items) {
  return items.flatMap(item => [
    item.name,
    ...(item.children ? getAllNames(item.children) : [])
  ]);
}

console.log(getAllNames(menuTree)); 
// ['文件', '新建', '打开', '从云端']

十、总结:一句话记住各方案

  • flat():官方指定快乐锤 🔨
  • reduce:面试必备手写题 ✍️
  • toString:数字数组急救包 🚑
  • 生成器:海量数据救世主 🦸
  • 栈迭代:深度嵌套终结者 💣
  • flatMap:过滤展开二合一 🥇

最后灵魂提问:你们团队用什么方案?有没有更骚的操作?评论区见真章! 👇

相关推荐
zwjapple1 小时前
docker-compose一键部署全栈项目。springboot后端,react前端
前端·spring boot·docker
像风一样自由20203 小时前
HTML与JavaScript:构建动态交互式Web页面的基石
前端·javascript·html
aiprtem4 小时前
基于Flutter的web登录设计
前端·flutter
浪裡遊4 小时前
React Hooks全面解析:从基础到高级的实用指南
开发语言·前端·javascript·react.js·node.js·ecmascript·php
why技术4 小时前
Stack Overflow,轰然倒下!
前端·人工智能·后端
GISer_Jing4 小时前
0704-0706上海,又聚上了
前端·新浪微博
止观止4 小时前
深入探索 pnpm:高效磁盘利用与灵活的包管理解决方案
前端·pnpm·前端工程化·包管理器
whale fall4 小时前
npm install安装的node_modules是什么
前端·npm·node.js
烛阴4 小时前
简单入门Python装饰器
前端·python
袁煦丞5 小时前
数据库设计神器DrawDB:cpolar内网穿透实验室第595个成功挑战
前端·程序员·远程工作