javascript/js中Array、Set、Map数据结构特性及用法

前言

本文温习前端开发中常见的3种数据结构:数组Array、有序集合Set、有序映射Map,并分别介绍其特性、用法示例

数组-Array

适用于存放和读取有序集合、不要求集合元素唯一性时;可通过索引快速访问元素,实现元素增删改查时

使用方法

1.创建、修改

    // 直接创建let arr = [6,7,8,9,0];// 使用构造函数创建// arr = new Array(6,7,8,9,0);console.log('len:',arr.length); // len: 5// 得到数组长度要用length而不是sizeconsole.log('size:',arr.size) // size: undefinedconsole.log(arr.at(0)); // 6console.log(arr[0]); // 6arr[0] = 100;  // 修改指定位置的元素console.log(arr); // [ 100, 7, 8, 9, 0 ]// fill(x,start?,end?)  从start索引开始填充元素x,end可选,end指定的位置不包含console.log(arr.fill(9999,2,4)); // [ 100, 7, 9999, 9999, 0 ]// 所有元素填充为 -1arr.fill(-1,0);console.log(arr); // [ -1, -1, -1, -1, -1 ]

2.添加删除元素

push添加,pop尾部删除,shift头部删除,unshift头部插入,concat合并数组

    let arr = [ 6, 7, 8, 9, 0 ]// push(x)尾部添加指定元素let len = arr.push(10);console.log("len:",len); // len: 6// pop() 尾部删除一个元素,并返回这个元素,若数组为空,返回undefinedlet lastVal = arr.pop();console.log("lastVal:",lastVal,", len:",arr.length); // lastVal: 10 , len: 5// shift() 头部删除一个元素,返回被删除元素,若数组为空返回undefinedlet delHeadVal = arr.shift();console.log("delHeadVal:",delHeadVal,",len:",arr.length); // delHeadVal: 6 ,len: 4// unshift(x1,x2,x3...)在元素开头插入一个或多个元素,返回插入后的数组长度len = arr.unshift(88);console.log("len:",len); // len: 5let arr2 = [2,4,6];// concat合并两个或多个数组,返回新的数组,注意arr不会发生改变let ansArr = arr.concat(arr2); console.log("ansArr len:",ansArr.length); // ansArr len: 8

slice拷贝数组元素

    let nums = [1, 2, 3, 4, 5, 6, 7];// slice(start,exclusiveEnd) 包括start,不包括exclusiveEnd,返回一个新数组对象,该方法不会改变原始数组let sliceNums = nums.slice(1, 3);console.log("sliceNums:", sliceNums); // sliceNums: [ 2, 3 ]sliceNums[0] = 888;// 修改sliceNums,不会改变原始数组numsconsole.log("nums:", nums); // nums: [ 1, 2, 3, 4, 5, 6, 7 ]// 从索引5开始提取所有的元素 console.log(nums.slice(4)); // [5, 6, 7 ]// 易错提示:-1表示倒数第1个元素,由于exclusiveEnd不包括,因此得到的最后一个元素是倒数第2个元素console.log(nums.slice(5, -1)); // [ 6 ]// slice() 提取所有元素console.log(nums.slice()); // [ 1, 2, 3, 4, 5, 6, 7 ]// slice 超出索引范围,返回一个空数组 []console.log(nums.slice(88)); // []

splice修改、删除、插入元素

    let nums = [1, 2, 3, 4, 5, 6, 7];// 删除指定位置的N个元素: nums.splice(index,count) 从index位置开始连续删除count个元素,并返回删除的元素,nums本身被改变let removedNums = nums.splice(2, 5);console.log("removedNums:", removedNums, ", nums:", nums); // removedNums: [ 3, 4, 5, 6, 7 ] , nums: [ 1, 2 ]// 元素替换:从索引1处删除0个元素(返回为空),并对原始数组添加多个元素,原始数组被改变console.log("res:",nums.splice(1, 0, 'x', 'y', 'z')); // res: []console.log("splice nums:", nums); // splice nums: [ 1, 'x', 'y', 'z', 2 ]// 删除后续元素:删除从索引2开始的所有元素,返回被删除元素console.log("removed: ", nums.splice(2), "nums:", nums); // removed:  [ 'y', 'z', 2 ] nums: [ 1, 'x' ]nums = [1, 2, 3, 4];// 删除索引2处的元素console.log("del: ", nums.splice(2, 1),", nums:",nums); // del:  [ 3 ] , nums: [ 1, 2, 4 ]// 将索引2处的1个元素删除,并替换为78,88nums.splice(2, 1, 78, 88);console.log("nums:", nums); // nums: [ 1, 2, 78, 88 ]

3.筛选、查找元素

filter筛选,find查找元素,findIndex、indexOf、lastIndexOf查找元素索引,includes判断是否包含

    let nums = [1, 2, 3, 4, 5, 6, 7];// filter过滤出符合指定规则的元素let evenNums = nums.filter(x => x % 2 == 0); // find查找数组中满足测试函数的第一个元素的值,若没有符合的,返回undefinedconsole.log("evenNums:", evenNums); // evenNums: [ 2, 4, 6 ]let targetValue = nums.find(x => x > 5);console.log("targetvalue:", targetValue); // targetvalue: 6// findIndex返回符合测试元素的第一个索引,找不到返回-1let targetIndex = nums.findIndex(x => x > 5);console.log("targetIndex:", targetIndex); //targetIndex: 5// indexOf(x)从索引位置0开始寻找一个指定的元素,找到则返回指向第一个元素的索引,找不到则返回-1console.log("index:", nums.indexOf(5)); // index: 4// indexOf(x,fromIndex) 从index位置寻找一个元素xconsole.log(nums.indexOf(1, 5));  // -1// lastIndexOf(x,fromIndex) 若fromIndex缺省,默认从最后一个位置开始向前查找x元素的索引console.log(nums.lastIndexOf(5)) // 4// includes(x)判断数组中是否包含一个指定元素,若包含返回true,否则falseconsole.log(nums.includes(4)); // true// includes(x,fromIndex) 从fromIndex位置开始查找是否包含指定元素console.log(nums.includes(2, 1)); // true

4.成分判断

every测试所有都符合、some测试至少一个元素符合

    let nums = [5, 8, 4, 6, 7];// every 判断所有元素是否都通过测试函数,若是返回true,否则falselet isAllEven = nums.every(x => x % 2 == 0);console.log("isAllEven:", isAllEven); // false// some 判断是否至少有一个元素通过测试函数,若是返回truelet hasEven = nums.some(x => x % 2 == 0);console.log("hasEven:", hasEven); // true

5.反转、排序

reverse反转数组顺序,sort排序

     let ids = new Array(2, 0, 3, 5, 1, 4);// reverse反转数组元素顺序,并返回数组本身let reverseIds = ids.reverse();console.log("reverseIds:", reverseIds); // reverseIds: [ 4, 1, 5, 3, 0, 2 ]console.log("ids:", ids); // ids: [ 4, 1, 5, 3, 0, 2 ]// sort排序会改变原始数组顺序,并返回数组本身,默认从小到大排序console.log(ids.sort()); // [ 0, 1, 2, 3, 4, 5 ]// 自定义排序,a-b升序,b-a降序ids.sort((a,b)=>b-a); console.log(ids);// [ 5, 4, 3, 2, 1, 0 ]

6.元素遍历

for…in遍历索引,for…of遍历元素, forEach遍历元素及索引

   let nums = [5, 8, 4, 6, 7];// for...in遍历数组,遍历的是索引for (let index in nums) {console.log("index:", index, ", value:", nums[index]);}// for...of遍历数组,遍历得到的是具体元素for (let x of nums) {console.log("x=", x);}// forEach遍历元素nums.forEach(x => {console.log("x:", x);});// forEach两个参数时第2个元素是索引nums.forEach((x, index) => {console.log("x:", x, ", index:", index);});// 普通遍历方法for (let i = 0; i < nums.length; i++) {console.log("nusm:", nums[i]);}

7.累计、分组运算

reduce对数字元素进行算术累计运算,对字符串连接运算

    let nums = [1, 2, 3];let initVal = 0;// reduce对数组中每个元素执行一个函数,将结果汇总为单个值返回,initVal指定初始值,preVal+curVal表示将数组元素累加let sums = nums.reduce((preVal, curVal) => preVal + curVal, initVal);console.log("sums:", sums); // 6const words = ['Hello', 'World', 'JavaScript'];// reduce将元素连接为一个字符串const sentence = words.reduce((accumulator, currentValue) => accumulator + ' ' + currentValue);console.log("sentence:"+sentence); // sentence:Hello World JavaScript// join将所有元素用字符-连接为一个字符串let str = nums.join('-');console.log(str); // 1-2-3

reduce分组

  const users = [{name:"User-A",age:21},{name:'User-B',age:20},{name:'User-C',age:20},{name:'User-E',age:20}];let initVal = {};let ageGroup = users.reduce((preVal,curVal)=>{let age = curVal.age;if(!preVal[age]){preVal[age] = [];}preVal[age].push(curVal);return preVal;},initVal);console.log(ageGroup);// {//     '20': [//       { name: 'User-B', age: 20 },//       { name: 'User-C', age: 20 },//       { name: 'User-E', age: 20 }//     ],//     '21': [ { name: 'User-A', age: 21 } ]//   }

8.变换

map、flatMap将每个元素进行变换

    let nums = [1, 2, 3];console.log(nums.map(x=>'id-'+x)); // [ 'id-1', 'id-2', 'id-3' ]// map:对数组中的每个元素执行回调函数,回调函数的返回值作为元素let ans = nums.map(x=>[x*2]);console.log(ans); // [ [ 2 ], [ 4 ], [ 6 ] ]// flatMap: 对每个元素执行回调函数,并将结果展平一层后返回一个新数组,相当于先执行 map,然后再执行 flatlet ans2 = nums.flatMap(x=>[x*2]);console.log(ans2); // [ 2, 4, 6 ]let nums2 = nums.map(x=>[x,x*x]);console.log(nums2); // [ [ 1, 1 ], [ 2, 4 ], [ 3, 9 ] ]let ans3 = nums.flatMap(x=>[x,x*x]); console.log(ans3); // [ 1, 1, 2, 4, 3, 9 ]

有序集合-Set

用于存储具有唯一性的元素,常用于元素查找、去重场景

使用方法

1.元素去重

普通类型插入元素唯一,可用于元素去重,对象插入是否唯一根据引用判断

   let arr = [1,2,2,3,1];// 数组转为集合去重let setNums = new Set(arr); // 集合转为数组console.log(Array.from(setNums)); // [ 1, 2, 3 ]let set = new Set();set.add(3);set.add(2);// 2已经存在,所以不会被重复添加set.add(2);// 获取集合大小要使用set.size,而不是set.length(输出为undefined)console.log("size:", set.size); // size: 2

2.元素存在

可以在内部表示为哈希表,查找时间复杂度为O(1)

    // set中是否含有某个元素let isContain = set.has(4);console.log("isContain:", isContain); // false

3.有序遍历

元素遍历时的顺序保持与插入顺序一致,可使用forEach或 for…of遍历

    let set = new Set([5,8,7,6]);// set集合的遍历应该使用 for...of而不是for...in,以下遍历什么也不会输出:// for(let id in set){//     console.log(id);// }// 遍历方法1:使用 for...of遍历for (let id of set) {console.log(id);}// 遍历方法2:使用forEachset.forEach(id => {console.log("id:", id);});// 获取迭代器对象,set.values()迭代器遍历,仍然要使用 for...of而不是for...infor (let value of set.values()) {console.log("value:", value);}//输出的 key和value其实是一样的for (let [key, value] of set.entries()) {console.log("key:", key, "value:", value);}

4.删除操作

delete删除某个元素,clear清空集合

    // delete 删除集合中数字5,成功返回true,否则falselet isDel = set.delete(5);console.log("isDel:", isDel);set.clear();

有序映射-Map

Map 适合于频繁增删改键值对的场景,可确保的键唯一性,内部实现用的是哈希表,具有较好性能

使用方法

1.键值添加、更改

新增或修改set,取值get,判断存在has,删除delete

    let map = new Map();// set进行键值添加map.set("name", "Alice");map.set("age", 24);// 键已存在则会被更新map.set("name", "Blob");// 注意:Map不要使用[]操作符,这种设置属性的方式不会改变 Map 的数据结构,它使用的是通用对象的特性,因此使用has是查不到的// ap['gender'] = 'female';// console.log('! has:', map.has('gender')); // falseconsole.log(map.has('name')); // trueconsole.log(Array.from(map.entries())); // [ [ 'name', 'lisi' ], [ 1, 'apple' ] ]// 取与键关联的值,若不存在则返回undefinedlet value = map.get("name");console.log("value:", value); // value: Blob// 获取map大小使用size,而不是lengthconsole.log(map.size); // 2map.clear();

2.有序遍历

Map 的键是有序的,遍历输出保持与添加时的顺序一致

Map遍历for…of或forEach

    // 使用可迭代对象初始化Maplet userMap = new Map([['id', 23], ['name', 'zhangsan'], ['age', 18]]);console.log(userMap);// for...of 遍历Mapfor (const [key, value] of userMap) {console.log("key:", key, ",value:", value);}// 或者for (const [key, value] of userMap.entries()) {console.log("key#:", key, ",value#:", value);}// 或者for (let entry of userMap) {console.log("entry:", entry);// entry[0]为键,entry[1]为值// console.log(entry[0],entry[1])}// forEach遍历mapuserMap.forEach((value, key) => {console.log("value=", value, ",key=", key);});for (const key of userMap.keys()) {console.log("key:", key);}for (const value of userMap.values()) {console.log('value:', value);}

关于Map映射与普通Object对象的区别

1.键的有序性:

Map 中的键以简单、直接的方式排序,Map 对象按照插入的顺序迭代条目、键和值

Object 的键排序比较复杂的,最好不要依赖属性的顺序

2.键的类型:

Map 的键可以为任何值(包括函数、对象或任何原始值)

Object 的键必须为 String 或 Symbol

3.大小计算:

Map 中的项目数量确定很容易从其 size 属性中获得

Object 中的项目数量确定比较麻烦,效率也较低,一种常见的方法是通过获取 Object.keys() 返回的数组的长度

4.其他方面:

Map 性能在涉及频繁添加和删除键值对的场景中表现更好,而Object未针对频繁添加和删除键值对进行优化

关于普通Object用法

// 普通对象
// 添加或修改属性obj[property],或obj.property,
// 遍历for...in(遍历key), for...of(遍历entries)function testObject2() {// 创建一个空对象let obj = {};obj[2] = 'zhangsan';obj[1] = 'lisi';console.log(obj);obj.msg = "hello";console.log(obj);// 判断对象是否有某个属性console.log(obj.hasOwnProperty("msg")); // trueconsole.log('msg' in obj); // truefor (let key in obj) {console.log("key:", key, "value:", obj[key]);}// 遍历键值对Object.entries(obj).forEach((key, value) => {console.log("key:", key, ", value:", value);});for (const [key, value] of Object.entries(obj)) {console.log("key=", key, ", value=", value);}// 类似:Object.values(obj);Object.keys(obj).forEach(key => {console.log("key=", key);});// delete删除某个属性,删除后再访问该属性为undefineddelete obj.msg;console.log(obj); // { '1': 'lisi', '2': 'zhangsan' }console.log(obj.msg); // undefined// 键的个数console.log(Object.keys(obj).length); // 2
}

参考资料

1.JavaScript 标准内置对象

2.JavaScript数据类型

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

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

相关文章

山东省安管人员考核报名流程及免冠证件照处理方法

随着《交通运输工程施工单位主要负责人、项目负责人和专职安全生产管理人员安全生产考核管理办法》&#xff08;以下简称《办法》&#xff09;的发布&#xff0c;山东省的安管人员迎来了新的考核要求。本文将为您详细解读山东省安管人员考核的报名流程&#xff0c;并提供免冠证…

【MotionCap】搭建wsl2的pytorch环境

参考大神:wsl2-ubuntu版本 cuda下周cuda11.3 wget https://developer.download.nvidia.com/compute/cuda/11.3.0/local_installers/cuda_11.3.0_465.19.01_linux.run sudo sh cuda_11.3.0_465.19.01_linux.run cuda是开源的么?下15分钟

1、什么是SSD?

概念 SSD&#xff08;Solid State Drive&#xff09;固态硬盘&#xff0c;是以闪存为介质的存储设备&#xff1b;这里突出的重点是闪存。 闪存&#xff0c;也就是常说的flash&#xff0c;分为NOR 和 NAND&#xff1b; NOR的地址线和数据线分开&#xff0c;所以NOR芯片可以像…

vue html2canvas 将html转图片时遇到的问题解决

问题1&#xff1a; 场景为将富文本组件tinymce里的html内容转为图片&#xff0c;出现的问题是vue获取不到tinymce元素&#xff0c;无法直接使用html2canvas 解决1&#xff1a; 将富文本内容渲染出来&#xff0c;推荐做法是将提交按钮改为预览按钮&#xff0c;然后在另外的弹…

“一带一路”再奏强音!秘鲁总统博鲁阿尔特参访苏州金龙

6月27日下午&#xff0c;首次访华的秘鲁共和国总统博鲁阿尔特一行到苏州金龙参观访问&#xff0c;受到了苏州金龙总经理黄书平的热情接待。 黄书平&#xff08;左二&#xff09;向博鲁阿尔特&#xff08;右一&#xff09;介绍苏州金龙发展情况 从苏州金龙发展历程、产品技术研…

Python中的爬虫实战:百度知道爬虫

python作为一种强大的编程语言&#xff0c;可以帮助我们更便捷地获取互联网上的大量数据。其中&#xff0c;爬虫技术是极具代表性的一部分。爬虫可以在互联网上获取各种数据并进行分析&#xff0c;为我们提供大量的有价值的信息。在python中&#xff0c;爬虫技术也能够得到广泛…

使用Nginx反向代理KKFileView遇到问题

使用KKFileView 4.0 以上版本 在KKFileView官网上&#xff0c;关于使用Nginx代理&#xff0c;建议配置如下 一、修改Nacos 在Nginx的conf文件夹中修改 nginx.conf ,新加 红框内的IP地址为代理服务器地址&#xff08;即安装KKFileView的服务器地址&#xff09; 二、修改KKFil…

小程序打包

一、manifest.json文件添加小程序id 二、接口校验&#xff0c;后端接口添加正式上线&#xff0c;有域名的地址 然后到微信公众平台-开发管理-服务器域名处配置request合法域名&#xff0c;在 此处能够看到后端的baseUrl 三、项目部署 四、发版 在小程序编辑器里 此处可以在…

Android Studio 2023版本切换DNK版本

选择自己需要的版本下载 根目录下的配置路劲注意切换 build.gradle文件下的ndkVersion也要配好对应版本

数据可视化宝典:Jupyter Notebook与Matplotlib的完美融合

数据可视化宝典&#xff1a;Jupyter Notebook与Matplotlib的完美融合 在数据科学的世界里&#xff0c;数据可视化是一种艺术&#xff0c;它能够将复杂的数据转换为直观的图形&#xff0c;让洞察变得触手可及。Jupyter Notebook是一个强大的工具&#xff0c;它支持多种编程语言…

Postman接口测试工具的原理及应用详解(五)

本系列文章简介&#xff1a; 在当今软件开发的世界中&#xff0c;接口测试作为保证软件质量的重要一环&#xff0c;其重要性不言而喻。随着前后端分离开发模式的普及&#xff0c;接口测试已成为连接前后端开发的桥梁&#xff0c;确保前后端之间的数据交互准确无误。在这样的背景…

Parade接口芯片选型和应用,点击查看!

01 常见数据 / 媒体接口电路 接口电路是电子设备之间&#xff0c;电子设备与外围设备之间&#xff0c;电子设备内部部件之间起连接作用的逻辑电路&#xff0c;接口电路是设备处理器与外部设备进行信息交互的桥梁。 图1&#xff1a;常见高速数据/多媒体接口 1.1 USB接口 从最早…

代谢组数据分析十:偏相关分析

欢迎大家关注全网生信学习者系列: WX公zhong号:生信学习者Xiao hong书:生信学习者知hu:生信学习者CDSN:生信学习者2介绍 偏相关分析是一种统计方法,用于在控制一个或多个其他变量的影响下,分析两个变量之间的相关性。当研究者想要了解两个变量之间的内在联系,但又担心…

详细配置SQL Server的链接服务器(图文操作Mysql数据库)

目录 前言1. MySQL ODBC 驱动2. 配置 SQL Server 链接服务器3. 彩蛋前言 此处配置以及安装没有什么理论知识 所以直奔主题,跟着以下步骤配置安装即可 需求:准备在10.197.0.110中链接外部的10.197.0.96的mysql数据源 已默认在10.197.0.96中安装了MySQL数据库并且知道其连接信…

PPT中的文字跟随Excel动态变化,且保留文字格式

今天协助客户解决了一个有趣的问题&#xff0c;这里记录一下&#xff0c;以此共勉。 目录 1. 提出问题2. 此功能的应用场景3. 开始制作4. 注意事项5. 若遇到任何问题 1. 提出问题 PPT的图表是可以引用Excel的&#xff0c;那PPT的文本是否可以引用Excel实现动态更新呢&#xff…

MWCSH 2024丨美格智能亮相上海世界移动通信大会,加速5G+AIoT应用进程

6月26日—28日全球通信领域最具规模和影响力的通信盛事—2024MWC上海世界移动通信大会在上海新国际博览中心隆重举行。MWC上海是亚洲连接生态系统的风向标&#xff0c;本届大会以“未来先行&#xff08;Future First&#xff09;”为主题&#xff0c;聚焦“超越5G”“人工智能经…

Quectel EM05-CE 模块测试

作者简介&#xff1a; 一个平凡而乐于分享的小比特&#xff0c;中南民族大学通信工程专业研究生在读&#xff0c;研究方向无线联邦学习 擅长领域&#xff1a;驱动开发&#xff0c;嵌入式软件开发&#xff0c;BSP开发 作者主页&#xff1a;一个平凡而乐于分享的小比特的个人主页…

HarmonyOS开发实战:加密类组件使用方法-API

加密类组件 模块介绍RSA提RSA供生成密钥加解密验签等系列方法(基于HarmonyOS API)AES提供AES生成密钥加解密等系列方法(基于HarmonyOS API)DES提供3DES生成密钥加解密等系列方法(基于HarmonyOS API)SM2提供SM2生成密钥加解密等系列方法(基于HarmonyOS API)SM3提供SM3生成摘要,…

蜜雪冰城小程序逆向

app和小程序算法一样 小程序是wasm

element-plus 2.7.6相关使用方式

1、按需导入时如何进行组件库语言切换&#xff1a; <template><el-config-provider :locale"zhCn"><el-table :data"tableData" style"width: 100%"> ...</el-table></el-config-provider> </template><…