JavaScript 常用数组方法之数组扁平化「赶紧收藏」

news2024/11/15 18:02:16

一、什么是数组扁平化

数组扁平化,就是将一个复杂的嵌套多层的数组,一层一层的转化为层级较少或者只有一层的数组。
比如:

// 多维数组
var arr = [1,2,[3,4,5,[6,7,8],9],10,[11,12]];
// 数组扁平化
[1,2,3,4,5,6,7,8,9,10,11,12]

二、实现方式

1. Array.prototype.flat([depth])

使用ES2019中新增的 Array.prototype.flat([depth]) 方法,该方法不会改变原数组,会返回一个新数组。
这个方法接收的可选参数 depth,表示扁平的深度,默认值为 1,表示扁平至一层的深度。
参数 Infinity 表示完全展开。

[1,2,[3]].flat()
// [1, 2, 3]

[1,2,[3,[4]]].flat(2)
// [1, 2, 3, 4]

// 终极解决方案
function flatten(arr) {
  return arr.flat(Infinity);
}
var arr = [1,2,[3,4,5,[6,7,8],9],10,[11,12]];
flatten(arr);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

关于flat

  • 完整语法:
    array.flat([depth]);

  • 扁平化嵌套了很多层的数组
    不知道要扁平的数组的具体深度,只想完全扁平这个嵌套数组里的成员话,可以使用 Infinity 这个值

  • 忽略数组空位
    flat() 方法有一个比较 cool 的地方在于,扁平数组的同时,还能移除数组中的空位(Empty Slots)。

    const arr = [1, ,3, ,5];
    arr.flat();
    // [1, 3, 5];
    
  • 浏览器支持
    flat() 是 ES2019 里定义的新特性,因此还是请大家忘记 Internet Explorer 和 Edge 吧😅
    在这里插入图片描述

2. 递归「for循环」

思路:采用普通递归,很好理解,通过for循环的方式,逐层逐个元素地去展平,如果当前元素不是数组,就执行push操作,是数组的话,就进行递归处理,再将递归处理的结果拼接到结果数组上,直至遍历完整个数组。

function flatten(arr){
	let res = [];
	if(Object.prototype.toString.call(arr) != "[object Array]"){return false};
	for(var i = 0; i < arr.length; i++){
		if(arr[i] instanceof Array){
			res = res.concat(flatten(arr[i]))	// concat 并不会改变原数组
			// res.push(...flatten(arr[i]));	// ...扩展运算符  
		}else{
			res.push(arr[i])
		}
	}
	return res;
};

var arr = [1,2,[3,4,5,[6,7,8],9],10,[11,12]];
flatten(arr);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

小Tips:

  1. 数组连接用concat,保证数组的原有维度不变;
  2. push会改变原始数据,并且没有铺平数组的功能,你传什么进去,就是什么。会导致数组的维度发生变化,增加了数组的维度;
  3. ...concat() 可以进行替换,可以算是2种方法,但是 ...扩展运算符,只适合降低一个维度。

3. while循环

思路:利用while判断加上some的遍历来实现扁平化。
some 目的是判断当前数组是否还有数组元素,如果有则对数组进行一层展开,同时将展开结果作为下一次判断的条件,当循环条件不满足时说明数组里已经没有数组元素了,这是数组已经完全扁平。

function flatten(arr) {
	while (arr.some(item => Array.isArray(item))) {
		arr = [].concat(...arr);
		// arr = [].concat.apply([], arr);
	}
	return arr;
}
var arr = [1,2,[3,4,5,[6,7,8],9],10,[11,12]];
flatten(arr); 
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

4. reduce方法

思路:reduce 是JS数组中非常强大的一个方法,同时也是JS中的一个函数式编程API。
前面的递归实现的关键就是对数组的每一项进行处理,遇到数组就递归处理它,既然需要循环和结果数组,那么我们可以使用reduce来简化它。

注意 reduce((prev,cur,index,arr)=>{},init) 用法:
接受两个参数,一个callback,一个初始值

  • callback的四个参数分别为,上一次 return的结果,当前项,当前索引,数组
  • 第二个参数是初始值,也是作为遍历的开始,我们这里设置一个空数组

reduce 实现什么功能取决于回调内部做了什么

function flatten(arr){
	if(Object.prototype.toString.call(arr) != "[object Array]"){return false};
	
	return arr.reduce((prev, cur)=>{
	    return prev.concat(Array.isArray(cur) ? flatten(cur) : cur)
	},[])
};
var arr = [1,2,[3,4,5,[6,7,8],9],10,[11,12]];
flatten(arr);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

5. toString + split

前提:要根据元素类型而定,比如数组的项全为数字
思路:先把数组使用toString()转换成字符串,这个过程会吧[]去掉,然后再调用split()方法转换成数组,最后把每一项转换为数组,即调用 map() 方法。

原理:toStringObject原型链上的一个方法,由于JS中所有对象都派生自Object对象,所以它们都能调用toString方法,只不过不同的对象可能会对这个方法进行改写以输出自己想要的格式。
数组的toString方法会将数组转换成一个元素间以逗号相隔的字符串,它内部会先将数组展平成一维后再转换成字符串,因此我们可以先利用toString进行展平,然后再通过split方法以逗号分隔每个元素来复原一个包含所有元素的数组,从而实现数组的扁平化。

注意:该方法具有一定的局限性,对于包含引用类型元素的数组来说,在 toString过程中会发生类型转换,从而使得转换结果异常,因为对于引用类型转成字符串,会调用引用类型的toString,上面提到不同对象会对它进行改写,例如函数就会得到一个函数体的代码字符串,而不是我们想要的函数引用。
所以,使用这种方式我们要看元素类型而定。

function flatten(arr) {
    return arr.toString().split(',').map(i => Number(i));
}
var arr = [1,2,[3,4,5,[6,7,8],9],10,[11,12]];
flatten(arr);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

6. JSON + 正则实现

思路:利用JSON.stringify()以及JSON.parse()方法,以及string中replace方法,将数组转换成字符串的表达形式,这里将数组转成字符串我们使用JSON.stringify方法,将数组转换成一个由括号包裹、元素间以逗号相隔的字符串,最后将括号全部替换成空字符,得到一个元素以逗号相隔字符串,最后将利用JSON.parse方法解析成数组对象。

function flatten(arr) {
  let str = JSON.stringify(arr);
  str = str.replace(/(\[|\])/g, '');
  // 拼接最外层,变成JSON能解析的格式
  str = '[' + str + ']';
  return JSON.parse(str); 
}
var arr = [1,2,[3,4,5,[6,7,8],9],10,[11,12]];
flatten(arr);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

注意:这种方式在处理引用数据类型上也有局限性,同时还要注意元素是否是JSON的合法数据类型。


小结

数组扁平化的方法是有很多种的,但是大致也可以分为三类:

  1. ES6 的 falt():他的性能是最好的,但是需要考虑浏览器兼容性的问题;
  2. 通过 for() while() reduce() 等递归遍历的方式;
  3. 使用toString JSON 等转为字符串的方式,去除括号,最终再转为数组的方式;

以上所有的方法demo都可使用,若有其他更好的方式,欢迎大佬补充,若文中有不对的地方,还请指正,及时改进,共同进步。

希望上面的内容对你的工作学习有所帮助!欢迎各位一键三连哦~

各位 加油!

原创不易,还希望各位大佬支持一下 \textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下

👍 点赞,你的认可是我创作的动力! \textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!

⭐️ 收藏,你的青睐是我努力的方向! \textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!

✏️ 评论,你的意见是我进步的财富! \textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/796822.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于在Python的for循环中改变列表的值问题探究

案例一&#xff1a; def test():a [1, 2]for i in a:print(i, id(a))if i 5:breaka [a[0]2, a[1]2] 输出&#xff1a; 1 4313456192 2 4313269056 解释&#xff1a; 在for循环语句中的变量a使用的内存地址为4313456192&#xff0c;这个地址以及存储的值不会因为a的重新赋…

ceph-mon运行原理分析

一、流程&#xff1a;ceph-deploy部署ceph-mon组建集群 1.ceph-deploy部署ceph-mon的工作流程及首次启动 1&#xff09;通过命令创建ceph-mon&#xff0c;命令为&#xff1a;ceph-deploy create mon keyring def mon(args):if args.subcommand create:mon_create(args)elif…

【Jenkins系列】-Pipeline语法全集

Jenkins为您提供了两种开发Pipeline的方式&#xff1a;脚本式和声明式。 脚本式流水线&#xff08;也称为“传统”流水线&#xff09;基于Groovy作为其特定于域的语言。而声明式流水线提供了简化且更友好的语法&#xff0c;并带有用于定义它们的特定语句&#xff0c;而无需学习…

金融行业软件测试面试题及其答案

下面是一些常见的金融行业软件测试面试题及其答案&#xff1a; 1. 什么是金融行业软件测试&#xff1f; 金融行业软件测试是针对金融领域的软件系统进行验证和确认的过程&#xff0c;旨在确保软件在安全、稳定、可靠和符合法规要求的条件下运行。 2. 解释一下金融软件中的风险…

golang,gin框架的请求参数(一)--推荐

golang&#xff0c;gin框架的请求参数&#xff08;一&#xff09; gin框架的重要性不过多的强调&#xff0c;重点就gin使用中的参数传递&#xff0c;获取进行梳理文件&#xff0c;满足使用需求。 获取前端请求参数的几种方法&#xff1a; 一、获取参数【浏览器地址获取参数】…

linux的一些基本指令第二期

rm rm -r 你要删除的目录名 加了-r 之后表示递归删除你要删除的目录 使用这个命名之后&#xff0c;他会一边递归到叶子节点&#xff0c;一边询问你是否要删除&#xff0c;然后会递归回来&#xff0c;在回来的途中删除&#xff1a; rm -rf 你要删除的目录名 强制执行删除操作…

权威认证!伙伴云入选亿欧2023AIGC应用场景创新TOP50榜单

近日, 知名科技与产业创新服务平台【亿欧】发布2023年度AIGC应用场景创新TOP50榜单。 伙伴云作为行业领先的零代码应用搭建平台&#xff0c;率先推出AI智能搭建系统功能&#xff0c;并将Chat GPT应用嵌入伙伴云应用在解决方案层&#xff0c;最终凭借前沿的技术创新力和突出的数…

【NVMe2.0d 17 - 1】Reservation 核心命令

文章目录 Reservation RegisterReservation AcquireReservation ReportReservation Release Reservation Register Reservation Register命令用于注册、取消注册或替换reservation key。 该命令使用Command Dword 10和内存中的Reservation Register data structure 如果该命…

基于seaborn.countplot的柱状图显示Y值及填充形状

参考链接&#xff1a; seaborn 柱状图上显示y值的方法 python柱形图填充 figs,ax plt.subplots(figsize(10,4)) fig sns.countplot(x"状态",hue"等级", datadatas)// 不可通过设置hatch参数来设置 marks ["o","---","***&quo…

IDEA批量启动多个微服务

注&#xff1a;现在盛行微服务开发&#xff0c;通常需要通过idea启动多个项目&#xff0c;每次都一个一个的启动&#xff0c;太麻烦了&#xff0c;不过被担心idea帮我们考虑到这个了&#xff08;不用安装插件哦&#xff09; 配置步骤&#xff1a; 将需要一次性全部启动的微服务…

[STL]详解vector模拟实现

[STL]vector模拟实现 文章目录 [STL]vector模拟实现1. 整体结构总览2. 成员变量解析3. 默认成员函数构造函数1构造函数2构造函数3拷贝构造函数析构函数 4. 迭代器相关函数begin函数end函数begin函数const版本end函数const版本 5.容量相关函数size函数capacity函数reserve函数re…

【Nodejs】操作mongodb数据库

1.简介 Mongoose是一个让我们可以通过Node来操作MongoDB的模块。Mongoose是一个对象文档模型(ODM)库,它对Node原生的MongoDB模块进行了进一步的优化封装&#xff0c;并提供了更多的功能。在大多数情况下&#xff0c;它被用来把结构化的模式应用到一个MongoDB集合&#xff0c;并…

【每日一题】2500. 删除每行中的最大值

【每日一题】2500. 删除每行中的最大值 2500. 删除每行中的最大值题目描述解题思路 2500. 删除每行中的最大值 题目描述 给你一个 m x n 大小的矩阵 grid &#xff0c;由若干正整数组成。 执行下述操作&#xff0c;直到 grid 变为空矩阵&#xff1a; 从每一行删除值最大的元…

阿里Java开发手册~建表规约

1. 【强制】表达是与否概念的字段&#xff0c;必须使用 is _ xxx 的方式命名&#xff0c;数据类型是 unsigned tinyint &#xff08; 1 表示是&#xff0c; 0 表示否 &#xff09; 。 说明&#xff1a; 任何字段如果为非负数&#xff0c;必须是 unsigned 。 正例&am…

Jenkins+Docker+Docker-Compose自动部署,SpringCloud架构公共包一个任务配置

前言 Jenkins和docker的安装&#xff0c;随便百度吧&#xff0c;实际场景中我们很多微服务的架构&#xff0c;都是有公共包&#xff0c;肯定是希望一个任务能够把公共包的配置加进去&#xff0c;一并构建&#xff0c;ok&#xff0c;直接上干货。 Jenkins 全局环境安装 pwd e…

建造者模式——复杂对象的组装与创建

1、简介 1.1、概述 建造者模式又称为生成器模式&#xff0c;它是一种较为复杂、使用频率也相对较低的创建型模式。建造者模式向客户端返回的不是一个简单的产品&#xff0c;而是一个由多个部件组成的复杂产品。 建造者模式是较为复杂的创建型模式&#xff0c;它将客户端与包…

【chatGpt】关于websocket连接中对未授权的捕捉问题

目录 问题 有效提问 有效的细节提问 问题 一路上&#xff0c;通过简单的error进行判断弹出授权&#xff0c;会有很多乱弹的现象&#xff1a; &#xff08;1&#xff09;链路正常切换会断 &#xff08;2&#xff09;服务器没有启动会连接不上 &#xff08;3&#xff09;没…

Pytorch深度学习-----DataLoader的用法

系列文章目录 PyTorch深度学习——Anaconda和PyTorch安装 Pytorch深度学习-----数据模块Dataset类 Pytorch深度学习------TensorBoard的使用 Pytorch深度学习------Torchvision中Transforms的使用&#xff08;ToTensor&#xff0c;Normalize&#xff0c;Resize &#xff0c;Co…

【Golang】基于OAuth2.0微信扫码实现客户端用户登录(原理+代码实现+视频讲解)

前言: 细心汇总,包括原理+配置+代码详细实现 文章目录 原理讲解什么是OAuth2.0解决方案授权码模式讲解认证流程Go语言实现微信扫码登录1. 内网穿透配置2. 微信测试账号申请3. 验证和微信服务器连接二维码生成回调地址测试原理讲解 什么是OAuth2.0 OAuth 2.0是一种授权协议,…

JavaScript学习 --消息摘要算法

消息摘要算法&#xff08;也称哈希算法&#xff09;是一种将任意大小的数据转换为一个固定大小的数据序列的算法。在JavaScript中&#xff0c;常见的消息摘要算法包括MD5、SHA-1、SHA-256等。它们适用于安全传输敏感数据、防篡改数据等场景。在本篇博客中&#xff0c;我们将介绍…