JavaScript系列(8)-- Array高级操作
JavaScript Array高级操作 📚
在前七篇文章中,我们探讨了JavaScript的语言特性、ECMAScript标准、引擎工作原理、数值类型、字符串处理、Symbol类型和Object高级特性。今天,让我们深入了解JavaScript中的Array高级操作。数组是最常用的数据结构之一,掌握其高级操作可以让我们更优雅地处理数据。
数组基础回顾 🌟
💡 小知识:JavaScript中的数组实际上是一种特殊的对象,它的索引是字符串类型的数字,并且有一个特殊的length属性。这种实现方式使得JavaScript数组比传统的数组更灵活,但在某些情况下性能可能不如传统数组。
数组的创建和初始化 📊
// 1. 数组创建的多种方式
function arrayCreation() {// 字面量方式const arr1 = [1, 2, 3, 4, 5];// 构造函数方式const arr2 = new Array(3); // 创建长度为3的空数组const arr3 = new Array(1, 2, 3); // 创建包含1,2,3的数组// Array.from方式const arr4 = Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']const arr5 = Array.from({ length: 5 }, (_, i) => i + 1); // [1, 2, 3, 4, 5]// Array.of方式const arr6 = Array.of(3); // [3]const arr7 = Array.of(1, 2, 3); // [1, 2, 3]// 扩展运算符const existing = [1, 2, 3];const arr8 = [...existing, 4, 5]; // [1, 2, 3, 4, 5]
}// 2. 类型化数组
function typedArrays() {// 创建类型化数组const int8Array = new Int8Array(4);const uint8Array = new Uint8Array(4);const int16Array = new Int16Array(4);const float32Array = new Float32Array(4);const float64Array = new Float64Array(4);// 从普通数组创建const numbers = [1, 2, 3, 4];const typed = new Int32Array(numbers);// 类型化数组的操作typed[0] = 10;console.log(typed.byteLength); // 字节长度console.log(typed.buffer); // 底层ArrayBuffer
}// 3. 数组缓冲区和视图
function arrayBuffers() {// 创建ArrayBufferconst buffer = new ArrayBuffer(16);// 创建不同的视图const int32View = new Int32Array(buffer);const float64View = new Float64Array(buffer);const uint8View = new Uint8Array(buffer);// 通过视图操作数据int32View[0] = 42;console.log(uint8View[0]); // 查看字节级表示
}
数组操作方法 🔧
JavaScript提供了丰富的数组操作方法:
// 1. 基本操作
function basicOperations() {const arr = [1, 2, 3, 4, 5];// 添加和删除元素arr.push(6); // 末尾添加arr.unshift(0); // 开头添加arr.pop(); // 末尾删除arr.shift(); // 开头删除// 切片和拼接const slice = arr.slice(1, 3); // 复制部分数组const spliced = arr.splice(1, 2, 'a', 'b'); // 替换元素// 合并数组const arr1 = [1, 2];const arr2 = [3, 4];const combined = arr1.concat(arr2);// 或使用扩展运算符const combined2 = [...arr1, ...arr2];
}// 2. 高阶函数操作
function higherOrderOperations() {const numbers = [1, 2, 3, 4, 5];// map: 转换每个元素const doubled = numbers.map(x => x * 2);// filter: 筛选元素const evens = numbers.filter(x => x % 2 === 0);// reduce: 累积计算const sum = numbers.reduce((acc, cur) => acc + cur, 0);// find/findIndex: 查找元素const found = numbers.find(x => x > 3);const foundIndex = numbers.findIndex(x => x > 3);// every/some: 条件检查const allPositive = numbers.every(x => x > 0);const hasEven = numbers.some(x => x % 2 === 0);// flatMap: 映射并展平结果const pairs = numbers.flatMap(x => [x, x * 2]);
}// 3. 排序和搜索
function sortingAndSearching() {const items = [{ name: '苹果', price: 5 },{ name: '香蕉', price: 3 },{ name: '橙子', price: 4 }];// 基本排序items.sort((a, b) => a.price - b.price);// 自定义排序items.sort((a, b) => {if (a.name < b.name) return -1;if (a.name > b.name) return 1;return 0;});// 二分查找const numbers = [1, 3, 5, 7, 9, 11];const index = numbers.indexOf(7);// 自定义二分查找function binarySearch(arr, target) {let left = 0;let right = arr.length - 1;while (left <= right) {const mid = Math.floor((left + right) / 2);if (arr[mid] === target) return mid;if (arr[mid] < target) left = mid + 1;else right = mid - 1;}return -1;}
}
数组的高级技巧 🎯
让我们看看一些高级的数组操作技巧:
// 1. 数组去重
function arrayDeduplication() {// 使用Setfunction uniqueArray1(arr) {return [...new Set(arr)];}// 使用filterfunction uniqueArray2(arr) {return arr.filter((item, index) => arr.indexOf(item) === index);}// 使用reducefunction uniqueArray3(arr) {return arr.reduce((unique, item) => unique.includes(item) ? unique : [...unique, item], []);}// 对象数组去重function uniqueObjectArray(arr, key) {const seen = new Set();return arr.filter(item => {const value = item[key];if (seen.has(value)) return false;seen.add(value);return true;});}
}// 2. 数组分组和分块
function arrayGrouping() {// 按条件分组function groupBy(arr, key) {return arr.reduce((groups, item) => {const value = typeof key === 'function' ? key(item) : item[key];(groups[value] = groups[value] || []).push(item);return groups;}, {});}// 分块function chunk(arr, size) {return Array.from({ length: Math.ceil(arr.length / size) },(_, i) => arr.slice(i * size, (i + 1) * size));}// 按数量分割function partition(arr, n) {const size = Math.ceil(arr.length / n);return chunk(arr, size);}
}// 3. 数组交集、并集和差集
function arraySetOperations() {// 交集function intersection(arr1, arr2) {return arr1.filter(item => arr2.includes(item));}// 并集function union(arr1, arr2) {return [...new Set([...arr1, ...arr2])];}// 差集function difference(arr1, arr2) {return arr1.filter(item => !arr2.includes(item));}// 对称差集function symmetricDifference(arr1, arr2) {return arr1.filter(item => !arr2.includes(item)).concat(arr2.filter(item => !arr1.includes(item)));}
}
数组性能优化 ⚡
处理大型数组时的性能优化技巧:
// 1. 预分配内存
function memoryPreallocation() {// 预分配数组大小const n = 1000000;const arr = new Array(n);// 不好的做法const dynamicArr = [];for (let i = 0; i < n; i++) {dynamicArr.push(i); // 可能导致多次重新分配内存}// 好的做法const preallocatedArr = new Array(n);for (let i = 0; i < n; i++) {preallocatedArr[i] = i;}
}// 2. 批量操作优化
function batchOperations() {// 使用TypedArray进行数值计算function computeSum(arr) {const typed = new Float64Array(arr);let sum = 0;for (let i = 0; i < typed.length; i++) {sum += typed[i];}return sum;}// 批量插入优化function batchInsert(arr, items) {const temp = [...arr];temp.push(...items);return temp;}
}// 3. 迭代器优化
function iteratorOptimization() {// 使用for...of代替forEachfunction sumArray(arr) {let sum = 0;for (const num of arr) {sum += num;}return sum;}// 使用迭代器处理大数据function* chunks(arr, size) {for (let i = 0; i < arr.length; i += size) {yield arr.slice(i, i + size);}}
}
实际应用场景 💼
让我们看看数组在实际开发中的一些应用:
// 1. 数据处理
class DataProcessor {// 数据转换static transform(data, transformers) {return data.map(item => transformers.reduce((acc, transformer) => transformer(acc), item));}// 数据过滤和排序static filterAndSort(data, filters, sorter) {return data.filter(item => filters.every(filter => filter(item))).sort(sorter);}// 数据聚合static aggregate(data, groupBy, aggregator) {const groups = this.groupBy(data, groupBy);return Object.entries(groups).map(([key, group]) => ({key,value: aggregator(group)}));}
}// 2. 虚拟列表
class VirtualList {constructor(data, pageSize) {this.data = data;this.pageSize = pageSize;this.currentPage = 0;}getCurrentPage() {const start = this.currentPage * this.pageSize;return this.data.slice(start, start + this.pageSize);}next() {if (this.hasNext()) {this.currentPage++;return this.getCurrentPage();}return [];}previous() {if (this.hasPrevious()) {this.currentPage--;return this.getCurrentPage();}return [];}hasNext() {return (this.currentPage + 1) * this.pageSize < this.data.length;}hasPrevious() {return this.currentPage > 0;}
}// 3. 数据缓存
class ArrayCache {constructor(maxSize = 1000) {this.maxSize = maxSize;this.cache = new Map();}set(key, array) {if (this.cache.size >= this.maxSize) {const firstKey = this.cache.keys().next().value;this.cache.delete(firstKey);}this.cache.set(key, array);}get(key) {return this.cache.get(key);}has(key) {return this.cache.has(key);}clear() {this.cache.clear();}
}
最佳实践建议 💡
- 数组操作最佳实践
// 1. 避免稀疏数组
function avoidSparseArrays() {// 不好的做法const sparse = [1, , 3];// 好的做法const dense = [1, null, 3];// 转换稀疏数组为密集数组const densified = sparse.filter(() => true);
}// 2. 使用合适的数组方法
function chooseRightMethods() {const arr = [1, 2, 3, 4, 5];// 查找元素// 不好的做法const found1 = arr.filter(x => x === 3)[0];// 好的做法const found2 = arr.find(x => x === 3);// 转换数组// 不好的做法const transformed1 = arr.reduce((acc, x) => [...acc, x * 2], []);// 好的做法const transformed2 = arr.map(x => x * 2);
}// 3. 性能考虑
function performanceConsiderations() {// 避免频繁修改数组长度const arr = [];const n = 1000;// 不好的做法for (let i = 0; i < n; i++) {arr.push(i);}// 好的做法const arr2 = Array.from({ length: n }, (_, i) => i);
}
- 错误处理和验证
// 1. 数组验证
function validateArray(arr) {if (!Array.isArray(arr)) {throw new TypeError('参数必须是数组');}if (arr.length === 0) {throw new Error('数组不能为空');}return true;
}// 2. 安全的数组操作
function safeArrayOperations() {function safeGet(arr, index, defaultValue = null) {if (!Array.isArray(arr)) return defaultValue;if (index < 0 || index >= arr.length) return defaultValue;return arr[index];}function safeSplice(arr, start, deleteCount, ...items) {const copy = [...arr];copy.splice(start, deleteCount, ...items);return copy;}
}// 3. 类型检查
function arrayTypeChecking() {function isNumberArray(arr) {return Array.isArray(arr) && arr.every(x => typeof x === 'number');}function isObjectArray(arr) {return Array.isArray(arr) && arr.every(x => x && typeof x === 'object');}
}
结语 📝
JavaScript的数组操作非常强大和灵活,掌握这些高级操作可以帮助我们更好地处理数据。我们学习了:
- 数组的创建和初始化方法
- 常用的数组操作方法
- 高级数组操作技巧
- 性能优化和最佳实践
- 实际应用场景
💡 学习建议:在处理数组时,要根据具体场景选择合适的方法,注意性能影响,特别是在处理大型数组时。同时,要注意数组操作的副作用,优先使用不改变原数组的方法。
如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇
终身学习,共同成长。
咱们下一期见
💻
相关文章:
JavaScript系列(8)-- Array高级操作
JavaScript Array高级操作 📚 在前七篇文章中,我们探讨了JavaScript的语言特性、ECMAScript标准、引擎工作原理、数值类型、字符串处理、Symbol类型和Object高级特性。今天,让我们深入了解JavaScript中的Array高级操作。数组是最常用的数据结…...
Harmony开发【笔记1】报错解决(字段名写错了。。)
在利用axios从网络接收请求时,发现返回obj的code为“-1”,非常不解,利用console.log测试,更加不解,可知抛出错误是 “ E 其他错误: userName required”。但是我在测试时,它并没有体现为空,…...
MAC环境安装(卸载)软件
MAC环境安装(卸载)软件 jdknode安装node,并实现不同版本的切换背景 卸载node从node官网下载pkg安装的node卸载用 homebrew 安装的node如果你感觉删的不够干净,可以再细分删除验证删除结果 在macOS下创建home目录 jdk 1.下载jdk 先…...
【Vim Masterclass 笔记05】第 4 章:Vim 的帮助系统与同步练习(L14+L15+L16)
文章目录 Section 4:The Vim Help System(Vim 帮助系统)S04L14 Getting Help1 打开帮助系统2 退出帮助系统3 查看具体命令的帮助文档4 查看帮助文档中的主题5 帮助文档间的上翻、下翻6 关于 linewise7 查看光标所在术语名词的帮助文档8 关于退…...
Multisim更新:振幅调制器+解调器(含仿真程序+文档+原理图+PCB)
前言 继3年前设计的:Multisim:振幅调制器的设计(含仿真程序文档原理图PCB),有读者表示已经不能满足新需求,需要加上新的解调器功能😂😂😂,鸽了很久这里便安排…...
CentOS — 群组管理
文章目录 一、查看群组二、添加群组三、删除群组四、修改群组 Linux 系统中每个用户都属于一个特定的群组。 若不设置用户的群组,默认会创建一个和用户名一样的群组,并将用户分到该群组。 一、查看群组 groups 用户名:查看用户所属群组。 二…...
【pytorch】注意力机制-1
1 注意力提示 1.1 自主性的与非自主性的注意力提示 非自主性提示: 可以简单地使用参数化的全连接层,甚至是非参数化的最大汇聚层或平均汇聚层。 自主性提示 注意力机制与全连接层或汇聚层区别开来。在注意力机制的背景下,自主性提示被称为查…...
html 元素中的data-v-xxxxxx 是什么?为什么有的元素有?有的没有?
data-v-xxxxxx 在 HTML 中,data-v 属性通常与 Vue.js 或其他前端框架一起使用,特别是当这些框架结合 CSS 预处理器(如 Sass、Less)和单文件组件(Single File Components, SFCs)时。data-v 属性的主要目的是…...
第27周:文献阅读及机器学习
目录 摘要 Abstract 一、文献阅读 发现问题 研究方法 CNN-LSTM DT SVR 创新点 案例分析 数据准备 模型性能 预测模型的实现 仿真实验及分析 二、LSTM 1、基本结构 2、具体步骤 3、举例说明 4、原理理解 总结 摘要 本周阅读文献《Short-term water qua…...
回归预测 | MATLAB实ELM-Adaboost多输入单输出回归预测
回归预测 | MATLAB实ELM-Adaboost多输入单输出回归预测 目录 回归预测 | MATLAB实ELM-Adaboost多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 一、极限学习机(ELM) 极限学习机是一种单层前馈神经网络,具有训练速…...
Swift Protocols(协议)、Extensions(扩展)、Error Handling(错误处理)、Generics(泛型)
最近在学习 Swift,总结相关知识 1. Protocols(协议) 1.1 协议的定义和实现 协议(protocol) 是一种定义方法和属性的蓝图,任何类、结构体或枚举都可以遵循协议。遵循协议后,需要实现协议中定义…...
.NET中的强名称和签名机制
.NET中的强名称(Strong Name)和签名机制是.NET Framework引入的一种安全性和版本控制机制。以下是关于.NET中强名称和签名机制的详细解释: 强名称 定义: 强名称是由程序集的标识加上公钥和数字签名组成的。程序集的标识包括简单文…...
使用 NestJS 构建高效且模块化的 Node.js 应用程序,从安装到第一个 API 端点:一步一步指南
一、安装 NestJS 要开始构建一个基于 NestJS 的应用,首先需要安装一系列依赖包。以下是必要的安装命令: npm i --save nestjs/core nestjs/common rxjs reflect-metadata nestjs/platform-express npm install -g ts-node包名介绍nestjs/coreNestJS 框…...
2025年大模型技术发展趋势展望:高速旋转的飞轮
2025年大模型技术发展趋势展望 引言1. 多模态大模型(MMM):从单一模态到高级模态融合2. 轻量化大模型:从大参数模型到小参数模型3. 强推理大模型:从概率生成到逻辑推理4. 移动端/边缘端Agent:从云端到本地5.…...
java中类的加载过程及各个阶段与运行时数据区中堆和方法区存储内容
java中类的加载过程 Java 类的加载是 JVM 将 字节码文件(.class 文件)加载到内存并最终转化为运行时数据的过程。它分为以下 五个主要阶段:加载、验证、准备、解析、初始化,每个阶段都有对应的内存位置存储相关信息。以下是类加载…...
渗透测试--Web基础漏洞利用技巧
渗透测试--Web基础漏洞利用技巧 本文章写了Web基础漏洞中一些不那么常见的利用技巧,而不谈及漏洞的原理以及常见用法。 SQL 俺是SQLmap党,哈哈,所以这块就不多讲了。详情可见文章《渗透测试--SQLmap_渗透测试sqlmap-CSDN博客》 XXE XXE组成…...
SpringBoot下载文件的几种方式
小文件:直接将文件一次性读取到内存中,文件大可能会导致OOM GetMapping("/download1")public void download1(HttpServletResponse response) throws IOException {// 指定要下载的文件File file new File("C:\\Users\\syd\\Desktop\\do…...
教程:从pycharm基于anaconda构建机器学习环境并运行第一个 Python 文件
1. 安装 PyCharm 访问 PyCharm 官方网站:https://www.jetbrains.com/pycharm/。下载社区版(免费)或专业版(收费,提供更多功能)。按照操作系统的安装指导安装 PyCharm。安装后打开 PyCharm,并根…...
我用Ai学Android Jetpack Compose之Button
答案来自 通义千问,代码同样需要到Android Studio里实践,才能学会。完整工程代码见文末。 我要学Button,麻烦介绍一下 当然可以!Button 是 Jetpack Compose 中用于创建可点击按钮的 Composable 函数。它提供了丰富的配置选项来定…...
修改secure-file-priv参数-mysql5.7.26限制不允许导入或导出的解决方法
文章目录 前言secure_file_priv参数说明修改secure_file_priv参数的步骤 前言 本人是在sql注入的文件上传拿web shel 时所用到的写入文件权限遇到文件上传不成功的问题,记住修改后,重启mysql才生效,最后可以查看验证一下。 secure_file_priv…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
