JavaScript实现一个函数,将数组扁平化(flatten),即把多维数组转为一维数组。
大白话实现一个函数,将数组扁平化(flatten),即把多维数组转为一维数组。
思路
实现数组扁平化的基本思路是遍历数组中的每个元素,如果元素是数组,就递归地将其扁平化并添加到结果数组中;如果元素不是数组,就直接添加到结果数组中。
代码示例
function flatten(arr) {// 创建一个空数组,用于存储扁平化后的结果let flattened = [];// 遍历输入数组中的每个元素for (let i = 0; i < arr.length; i++) {// 检查当前元素是否为数组if (Array.isArray(arr[i])) {// 如果当前元素是数组,递归调用 flatten 函数对其进行扁平化// 并将扁平化后的结果添加到 flattened 数组中flattened = flattened.concat(flatten(arr[i]));} else {// 如果当前元素不是数组,直接将其添加到 flattened 数组中flattened.push(arr[i]);}}// 返回扁平化后的数组return flattened;
}// 测试示例
const multiDimensionalArray = [1, [2, [3, 4], 5], 6, [7, 8]];
const flattenedArray = flatten(multiDimensionalArray);
console.log(flattenedArray);
代码解释
-
函数定义:
function flatten(arr):定义了一个名为flatten的函数,它接受一个数组arr作为参数。
-
初始化结果数组:
let flattened = [];:创建一个空数组flattened,用于存储扁平化后的结果。
-
遍历数组:
for (let i = 0; i < arr.length; i++):使用for循环遍历输入数组arr中的每个元素。
-
检查元素类型:
if (Array.isArray(arr[i])):使用Array.isArray方法检查当前元素是否为数组。
-
递归处理数组元素:
flattened = flattened.concat(flatten(arr[i]));:如果当前元素是数组,递归调用flatten函数对其进行扁平化,并使用concat方法将扁平化后的结果添加到flattened数组中。
-
处理非数组元素:
flattened.push(arr[i]);:如果当前元素不是数组,直接使用push方法将其添加到flattened数组中。
-
返回结果:
return flattened;:返回扁平化后的数组。
除了递归,还有其他方法可以实现数组扁平化吗?
除了递归方法,还有几种不同的方式可以实现数组扁平化,下面为你详细介绍:
方法一:使用 reduce 和 concat 方法
reduce 方法可以对数组中的每个元素执行一个提供的函数,并将其结果汇总为单个值。结合 concat 方法可以有效实现数组扁平化。
function flatten(arr) {// 使用 reduce 方法遍历数组return arr.reduce((acc, val) => {// 如果当前元素是数组,使用 concat 方法将其扁平化后添加到累加器中// 如果不是数组,直接添加到累加器中return acc.concat(Array.isArray(val)? flatten(val) : val);}, []);
}// 测试示例
const multiDimensionalArray = [1, [2, [3, 4], 5], 6, [7, 8]];
const flattenedArray = flatten(multiDimensionalArray);
console.log(flattenedArray);
此代码中,reduce 方法遍历数组的每个元素,若元素是数组,就递归调用 flatten 函数将其扁平化,再用 concat 方法添加到累加器;若不是数组则直接添加到累加器。
方法二:使用 flat 方法
flat 是 JavaScript 数组自带的方法,能直接实现数组扁平化。可以指定扁平化的深度,若要完全扁平化,可传入 Infinity。
const multiDimensionalArray = [1, [2, [3, 4], 5], 6, [7, 8]];
// 使用 flat 方法并传入 Infinity 实现完全扁平化
const flattenedArray = multiDimensionalArray.flat(Infinity);
console.log(flattenedArray);
这种方法简洁直观,直接调用 flat 方法并传入 Infinity 就能把多维数组完全扁平化为一维数组。
方法三:使用 while 循环和 some 方法
通过 some 方法检查数组中是否还有嵌套数组,若有就使用 concat 方法展开,借助 while 循环持续处理,直至没有嵌套数组。
function flatten(arr) {let isNested = true;// 当数组中还有嵌套数组时继续循环while (isNested) {isNested = false;let newArr = [];// 遍历数组for (let i = 0; i < arr.length; i++) {if (Array.isArray(arr[i])) {// 如果是数组,将其元素添加到新数组中newArr = newArr.concat(arr[i]);isNested = true;} else {// 不是数组则直接添加到新数组newArr.push(arr[i]);}}arr = newArr;}return arr;
}// 测试示例
const multiDimensionalArray = [1, [2, [3, 4], 5], 6, [7, 8]];
const flattenedArray = flatten(multiDimensionalArray);
console.log(flattenedArray);
此代码利用 while 循环和 some 方法不断检查并展开嵌套数组,直到数组中不存在嵌套数组,最终得到一维数组。
哪种方法实现数组扁平化的效率更高?
递归方法
function flatten(arr) {let flattened = [];for (let i = 0; i < arr.length; i++) {if (Array.isArray(arr[i])) {flattened = flattened.concat(flatten(arr[i]));} else {flattened.push(arr[i]);}}return flattened;
}
- 优点:代码逻辑直观,易于理解和实现,适合处理嵌套层级不深、数据规模较小的数组。
- 缺点:当数组嵌套层级很深时,递归调用会导致大量的函数调用栈,可能引发栈溢出错误,而且函数调用的开销也会使性能下降。
使用 reduce 和 concat 方法
function flatten(arr) {return arr.reduce((acc, val) => {return acc.concat(Array.isArray(val)? flatten(val) : val);}, []);
}
- 优点:代码简洁,同样基于递归思想,借助
reduce方法实现数组遍历和结果累加,处理逻辑清晰。 - 缺点:和递归方法一样,在处理深度嵌套数组时,由于递归调用过多,会有栈溢出风险,性能也会受影响。
使用 flat 方法
const flattenedArray = multiDimensionalArray.flat(Infinity);
- 优点:这是 JavaScript 原生提供的方法,由浏览器引擎底层实现,经过高度优化,性能通常较好。使用
Infinity作为参数能轻松处理任意嵌套深度的数组,代码简洁高效。 - 缺点:该方法是 ES2019 引入的新特性,对于一些较旧的浏览器版本可能不支持,需要做兼容性处理。
使用 while 循环和 some 方法
function flatten(arr) {let isNested = true;while (isNested) {isNested = false;let newArr = [];for (let i = 0; i < arr.length; i++) {if (Array.isArray(arr[i])) {newArr = newArr.concat(arr[i]);isNested = true;} else {newArr.push(arr[i]);}}arr = newArr;}return arr;
}
- 优点:避免了递归调用,不会有栈溢出问题,在处理深度嵌套数组时性能相对稳定。
- 缺点:代码逻辑相对复杂,需要多次遍历数组和创建新数组,在处理大规模数组时,频繁的数组操作会带来一定的性能开销。
效率总结
- 小规模、浅嵌套数组:递归方法、
reduce和concat方法代码简洁易读,性能差异不大,可任选其一。 - 大规模、深嵌套数组:
flat方法效率最高,因为它是原生方法,经过优化;若考虑兼容性,while循环和some方法是不错的选择,能避免栈溢出问题。
相关文章:
JavaScript实现一个函数,将数组扁平化(flatten),即把多维数组转为一维数组。
大白话实现一个函数,将数组扁平化(flatten),即把多维数组转为一维数组。 思路 实现数组扁平化的基本思路是遍历数组中的每个元素,如果元素是数组,就递归地将其扁平化并添加到结果数组中;如果元…...
SpringBoot最佳实践之 - 使用AOP记录操作日志
1. 前言 本篇博客是个人在工作中遇到的需求。针对此需求,开发了具体的实现代码。并不是普适的记录操作日志的方式。以阅读本篇博客的朋友,可以参考此篇博客中记录日志的方式,可能会对你有些许帮助和启发。 2. 需求描述 有一个后台管理系统…...
第六届机电一体化技术与智能制造国际学术会议(ICMTIM 2025)
重要信息 4月11-13日 南京江北新区工业大学亚朵酒店 www.icmtim.org(点击了解参会投稿等) 简介 由南京工业大学主办,南京工业大学电气工程与控制科学学院、中国矿业大学、黑龙江大学、江苏省自动化学会承办的第六届机电一体化技术…...
numpy学习笔记4:np.arange(0, 10, 2) 的详细解释
numpy学习笔记4:np.arange(0, 10, 2) 的详细解释 以下是 np.arange(0, 10, 2) 的详细解释: 1. 函数作用 np.arange() 是 NumPy 中用于生成均匀间隔数值序列的函数,类似于 Python 内置的 range(),但返回的是 NumPy 数组而非列表&…...
期刊分区表2025年名单下载(经济学、管理学)
2025年期刊分区表包括SCIE、SSCI、A&HCI、ESCI和OAJ,共设置了包括自然科学、社会科学和人文科学在内的21个大类 本次分享的是期刊分区表2025年名单经济学类、管理学类,一共7631025条 一、数据介绍 数据名称:期刊分区表2025年名单 数据…...
八股学习-JUC java并发编程
本文仅供个人学习使用,参考资料:JMM(Java 内存模型)详解 | JavaGuide 线程基础概念 用户线程:由用户空间程序管理和调度的线程,运行在用户空间。 内核线程:由操作系统内核管理和调度的线程&…...
嵌入式笔记 | 正点原子STM32F103ZET6 4 | 中断补充
1. 外设引脚重映射 1.1 定义 在STM32中,每个外设的引脚都有默认的GPIO端口,但有些引脚可以通过重映射寄存器将功能映射到其他端口。这种机制称为引脚重映射,主要用于解决引脚复用冲突或优化PCB布线。 1.2 重映射的类型 部分重映射&#x…...
PostgreSQL_数据下载并保存(psycopg2)
目录 前置: 1 数据下载 1.1 多个股票多个交易日 1.2 一个交易日所有股票 2 数据保存,使用python中的psycopg2包 2.1 在PyCharm中创建新项目,并安装包 2.2 代码-多个股票多个交易日 2.3 代码-一个交易日所有股票 2.4 在 pgAdmin4 中…...
启明星辰春招面试题
《网安面试指南》https://mp.weixin.qq.com/s/RIVYDmxI9g_TgGrpbdDKtA?token1860256701&langzh_CN 5000篇网安资料库https://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247486065&idx2&snb30ade8200e842743339d428f414475e&chksmc0e4732df793fa3bf39…...
边缘计算革命:重构软件架构的范式与未来
摘要 边缘计算通过将算力下沉至网络边缘,正在颠覆传统中心化软件架构的设计逻辑。本文系统分析了边缘计算对软件架构的范式革新,包括分布式分层架构、实时资源调度、安全防护体系等技术变革,并结合工业物联网、智慧医疗等场景案例,…...
【读点论文】Chain Replication for Supporting High Throughput and Availability
在分布式系统中,强一致性往往和高可用、高吞吐是矛盾的。比如传统的关系型数据库,其保证了强一致性,但往往牺牲了可用性和吞吐量。而像 NoSQL 数据库,虽然其吞吐量、和扩展性很高,但往往只支持最终一致性,无…...
Servlet、Servlet的5个接口方法、生命周期、以及模拟实现 HttpServlet 来写接口的基本原理
DAY15.1 Java核心基础 Servlet Servlet是一个接口,是java的基础,java之所以编写web的程序,接收请求并响应,就是因为Sevlet接口 Java 类实现了Servlet接口的时候就可以接收并响应请求,成为web服务器 Web服务器就是接…...
深入了解 C# 中的 LINQ:功能、语法与应用解析
1. 什么是 LINQ? LINQ(Language Integrated Query,语言集成查询)是 C# 和其他 .NET 语言中的一种强大的查询功能,它允许开发者在语言中直接执行查询操作。LINQ 使得开发者可以使用 C# 语法(或 VB.NET&…...
贝叶斯公式的一个直观解释
E E E:抓到娃娃 H H H:坐地铁 H ˉ \bar H Hˉ:坐公交 P ( E ) P ( H ) P ( E ∣ H ) P ( H ‾ ) P ( E ∣ H ‾ ) P({E}) P({H}) P({E} \mid {H}) {P}(\overline{{H}}) {P}({E} \mid \overline{{H}}) P(E)P(H)P(E∣H)P(H)P(E∣H) P (…...
Java 大视界 -- Java 大数据分布式计算中的通信优化与网络拓扑设计(145)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...
reconstruct_3d_object_model_for_matching例子
文章目录 1.获取om3文件2.准备可视化3.准备3D可视化4.读取3D模型5.显示成对注册结果16.显示成对注册结果27.联合注册模型8.处理图像8.1子采样8.2 图像计算与平滑8.3 三角测量 9.基于表面做3D匹配10.评估模型准确度10.1 在场景中找到模型10.2 计算模型和场景之间的距离 11.立体系…...
【JavaWeb学习Day27】
Tlias前端 员工管理 条件分页查询: 页面布局 搜索栏: <!-- 搜索栏 --><div class"container"><el-form :inline"true" :model"searchEmp" class"demo-form-inline"><el-form-item label…...
Webrtc编译官方示例实现视频通话
Webrtc编译官方示例实现视频通话 前言 webrtc官网demo中给了一个供我们学习和应用webrtc的一个很好的例子:peerconnection,这期我们就来编译和运行下这个程序看看视频通话的效果以。 1、打开源码工程 继上期源码编译完成后,我们使用vs打开…...
编程语言选择分析:C#、Rust、Go 与 TypeScript 编译器优化
编程语言选择分析:C#、Rust、Go 与 TypeScript 编译器优化 在讨论编程语言的选择时,特别是针对微软的 C# 和 Rust,以及谷歌的 Go 语言,以及微软试图通过 Go 来拯救 TypeScript 编译器的问题,我们可以从多个角度来分析和…...
信息学奥赛一本通 1610:玩具装箱 | 洛谷 P3195 [HNOI2008] 玩具装箱
【题目链接】 ybt 1610:玩具装箱 洛谷 P3195 [HNOI2008] 玩具装箱 【题目考点】 1. 动态规划:斜率优化动规 斜率优化动规模板题:信息学奥赛一本通 1607:【 例 2】任务安排 2 | 洛谷 P10979 任务安排 2 【解题思路】 玩具长度…...
数仓工具—Hive语法之不同纬度聚合
不同纬度聚合 提到不同纬度聚合,大家想到的肯定是grouping sets,或者是cube和rollup 其实这些我们之前都讲过,可以看看之前的文章 数仓工具—Hive语法之cube和rollup 数仓工具—Hive语法之grouping sets 但是我们今天遇到的问题是,使用的工具不支持grouping sets,既然…...
领码科技:在低代码技术浪潮中的分享与探索
前言: 25年的职业生涯,赋予了我深厚的技术积累与实践经验。从武汉大学的工测系毕业,到央企副总工的职位,我始终站在IT浪潮的最前沿。然而,离开企业后,我并未停止前行的脚步。从2024年11月起,我选…...
大数据学习(80)-数仓分层
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一…...
刘强东突然发声:不该用算法压榨最底层兄弟!东哥,真正的人民企业家
今天忙了一天,很累,准备睡觉的时候,看到网上盛传的刘强东的朋友圈,东哥又在朋友圈发文了。 说实话,看完之后,感动,真的感动。 尤其是当我看到这两句话的时候。 1、我们所学的知识、商业模式、技…...
Java 记忆链表,LinkedList 的升级版
文章目录 记忆链表 MemoryLinkedList实战源代码 众所周知,ArrayList 和 LinkedList 是 Java 集合中两个基本的数据结构,对应数据结构理论中的数组和链表。但在这两个数据结构,开发者们通常使用 ArrayList,而不使用 LinkedList。JD…...
【构建CV图像识别系统】从传统方法到深度学习
目录 1. 图像的基本概念1.1 像素与色彩1.2 过滤与卷积 2. 图像分类与检测3. 图像特征的提取3.1 全局特征3.2 局部特征3.2.1 边缘(Edge)3.2.2 角点(Corner)3.2.3 SIFT 特征 4. 传统方法与深度学习在图像识别中的应用4.1 基于传统方…...
.net core集成MQTT服务端
程序作为MQTT的服务端,也是WebApi 接口地址,在Web页面中MQTTJS用的是Websocker协议,在Winfrom中用MQTT协议。导致程序需要启动两个端口。直接上代码 创建服务 引用包:MQTTnet,MQTTnet.AspNetCore,这包最新…...
poetry安装与使用
文章目录 安装方法创建虚拟环境其他常用命令从 poetry.lock 中安装第三方依赖包 安装方法 安装命令(全局安装,不要在虚拟环境中安装,方便后面创建环境使用) pip install poetry修改虚拟环境路径(首次使用poetry时执行&…...
UVM config机制及uvm_resource_pool
目录 1. uvm_config_db 类源码 1.1 set 1.2 get 2. uvm_resource_pool 2.1 uvm_resource_pool::set 2.2 uvm_resource 3. usage 4. 小结 uvm提供一种uvm_config_db机制使得在仿真中通过变量设置来修改环境,使环境更加灵活。本文主要介绍uvm_config_db#(type)::get/set…...
JAVA学习*接口
接口 在生活中我们常听说USB接口,那接口是什么呢? 在Java中,接口相当于多个类的一种公共规范,是一种引用数据类型。 定义接口 public interface IUSB {public static final String SIZE "small";public abstract vo…...
