【09】ES6:Set 和 Map 数据结构
一、Set
1、基本语法
定义
Set 是一系列无序、没有重复值的数据集合。数组是一系列有序(下标索引)的数据集合。
Set 本身是一个构造函数,用来生成 Set 数据结构。
const s = new Set()
[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x))for (let i of s) {console.log(i)
}
// 2 3 5 4 // Set 中不能有重复的成员
参数
Set 函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。
// 数组作为参数
const s = new Set([1, 2, 1])
console.log(s) // Set(2) { 1, 2 }// 字符串作为参数
const s = new Set('hiii')
console.log(s) // Set(2) { 'h', 'i' }// arguments 作为参数
function func() {console.log(new Set(arguments))
}
func(1, 2, 1) // Set(2) { 1, 2 }// NodeList 作为参数
new Set(document.querySelectorAll('P'))// Set 作为参数(这也是复制一个 Set 的方法)
const s = new Set([1, 2, 1])
console.log(new Set(s)) // Set(2) { 1, 2 }
console.log(s) // Set(2) { 1, 2 }
注意事项
Set 对重复值的判断基本遵循严格相等(===)。
但是对于 NaN 的判断与 === 不同,Set 中 NaN 等于 NaN 。
2、Set 实例的方法和属性
【Set 实例的属性】
| 属性 | 说明 |
|---|---|
| Set.prototype.constructor | 构造函数,默认就是 Set 函数。 |
| Set.prototype.size | 返回 Set 实例的成员总数。 |
const s = new Set()
s.add(0)
s.add(1).add(2).add(2).add(3)s.size // 4
【Set 实例的方法】
| 操作方法(用于操作数据) | 说明 |
|---|---|
| Set.prototype.add(value) | 添加某个值,返回 Set 结构本身。 |
| Set.prototype.delete(value) | 删除某个值,返回一个布尔值,表示删除是否成功。 |
| Set.prototype.has(value) | 返回一个布尔值,表示该值是否为Set的成员。 |
| Set.prototype.clear() | 清除所有成员,没有返回值。 |
const s = new Set()
s.add(0)
s.add(1).add(2).add(2).add(3) // 可以连写
s // Set(4) { 0, 1, 2, 3 }s.has(1) // true
s.has(4) // falses.delete(2)
s.delete(4) // 使用 delete 删除不存在的成员,什么都不会发生,也不会报错
s // Set(3) { 0, 1, 3 }s.clear()
s // Set(0) {}
| 遍历方法(用于遍历成员) | 说明 |
|---|---|
| Set.prototype.keys() | 返回键名的遍历器。 |
| Set.prototype.values() | 返回键值的遍历器。 |
| Set.prototype.entries() | 返回键值对的遍历器。 |
| Set.prototype.forEach() | 使用回调函数遍历每个成员。 |
keys 方法、values 方法、entries 方法返回的都是遍历器对象。 由于 Set 结构没有键名,只有键值,所以 keys 方法和 values 方法的行为完全一致。
Set 结构的实例与数组一样,也拥有 forEach 方法,用于对每个成员执行某种操作,没有返回值。
let set = new Set(['red', 'green', 'blue'])for (let item of set.keys()) {console.log(item)
}
// red green bluefor (let item of set.values()) {console.log(item)
}
// red green bluefor (let item of set.entries()) {console.log(item)
}
// ['red', 'red'] ['green', 'green'] ['blue', 'blue']let set = new Set([1, 4, 9])
set.forEach((value, key) => console.log(key + ' : ' + value))
// 1 : 1
// 4 : 4
// 9 : 9
Set 结构的实例默认可遍历,它的默认遍历器生成函数就是它的 values 方法。
这意味着,可以省略 values 方法,直接用 for...of 循环遍历 Set。
Set.prototype[Symbol.iterator] === Set.prototype.values // truelet set = new Set(['red', 'green', 'blue'])
for (let x of set) {console.log(x)
}
// red green blue
3、Set 的应用
数组去重
扩展运算符(...)内部使用 for...of 循环,所以也可以用于 Set 结构。
[...new Set(array)]let arr = [3, 5, 2, 2, 5, 5]
let unique = [...new Set(arr)]
// [3, 5, 2]
Array.from() 方法可以将 Set 结构转为数组。
// Array.from 将类数组对象(array-like)和可遍历的对象(iterable)转换为真正的数组进行使用
function dedupe(array) {return Array.from(new Set(array))
}dedupe([1, 1, 2, 3]) // [1, 2, 3]
字符串去重
[...new Set(str)].join('')[...new Set('ababbc')].join('') // 'abc'
存放 DOM 元素
// 这里使用 Set 是因为我们不需要通过下标去访问,只需直接遍历即可
const s = new Set(document.querySelectorAll('p'))
s.forEach(function (elem) {elem.style.color = 'red'
})
遍历
数组的 map 和 filter 方法也可以间接用于 Set 了。
let set = new Set([1, 2, 3])
set = new Set([...set].map(x => x * 2))
// 返回Set结构:{2, 4, 6}let set = new Set([1, 2, 3, 4, 5])
set = new Set([...set].filter(x => (x % 2) == 0))
// 返回Set结构:{2, 4}
因此使用 Set 可以很容易地实现并集(Union)、交集(Intersect)和差集(Difference)。
let a = new Set([1, 2, 3])
let b = new Set([4, 3, 2])// 并集
let union = new Set([...a, ...b])
// Set {1, 2, 3, 4}// 交集
let intersect = new Set([...a].filter(x => b.has(x)))
// set {2, 3}// (a 相对于 b 的)差集
let difference = new Set([...a].filter(x => !b.has(x)))
// Set {1}
二、Map
1、基本语法
定义
Map 可以理解为:“映射”。Map 和 对象 都是键值对的集合。
Map 和 对象 的区别:
对象一般用字符串当作 “键”(当然在书写时字符串键的引号可以去掉)。
Map 中的 “键” 可以是一切类型。
// 键 ——> 值,key ——> value
// 对象:
const person = {name: 'alex',age: 18
}// Map:
const m = new Map()
m.set('name', 'alex')
m.set('age', 18)
console.log(m) // Map(2) { 'name' => 'alex', 'age' => 18 }// Map 中的 “键” 可以是一切类型。
const m = new Map()
m.set(true, 'true')
m.set({}, 'object')
m.set(new Set([1, 2]), 'set')
m.set(undefined, 'undefined')
console.log(m)
/*
Map(4) {true => 'true',{} => 'object',Set(2) { 1, 2 } => 'set',undefined => 'undefined'
}
*/
参数
任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构都可以当作 Map 构造函数的参数
例如:二维数组、Set、Map 等
new Map([['name', 'alex'],['age', 18]
]) // Map(2) { 'name' => '张三', 'age' => 18 }// 等价于
const items = [['name', 'alex'],['age', 18]
]
const map = new Map()
items.forEach(([key, value]) => map.set(key, value)
)
// Set
// Set 中也必须体现出键和值
const s = new Set([['name', 'alex'],['age', 18]
])
console.log(new Map(s)) // Map(2) { 'name' => 'alex', 'age' => 18 }
console.log(s) // Set(2) { [ 'name', 'alex' ], [ 'age', 18 ] }// Map
const m = new Map([['name', 'alex'],['age', 18]
])
console.log(m) // Map(2) { 'name' => 'alex', 'age' => 18 }
const m2 = new Map(m) // Map 复制的方法
console.log(m2, m2 === m) // Map(2) { 'name' => 'alex', 'age' => 18 } false
注意事项
在 Set 中遇到重复的值直接去掉后者,而 Map 中遇到重复的键值则是后面的覆盖前面的。
基本遵循严格相等(===),Map 中 NaN 也是等于 NaN。
2、Map 实例的方法和属性
【Map实例的属性】
| 属性 | 说明 |
|---|---|
| Map.prototype.constructor | 构造函数,默认就是 Map 函数。 |
| Map.prototype.size | 返回 Map 实例的成员总数 |
const map = new Map()
map.set('foo', true)
map.set('bar', false)map.size // 2
【Map实例的操作方法】
| 操作方法(用于操作数据) | 说明 |
|---|---|
| Map.prototype.set(key, value) | 设置键名 key 对应的键值为 value,然后返回整个 Map 结构。 |
| Map.prototype.get(key) | 读取 key 对应的键值,如果找不到 key,返回 undefined。 |
| Map.prototype.delete(key) | 删除某个值,返回一个布尔值,表示删除是否成功。 |
| Map.prototype.has(key) | 返回一个布尔值,表示某个键是否在当前 Map 对象之中。 |
| Map.prototype.clear() | 清除所有成员,没有返回值。 |
const m = new Map()
m.set('edition', 6) // 键是字符串
m.set(262, 'standard') // 键是数值
m.set(undefined, 'nah') // 键是 undefined
m.has('edition') // true
m.has('years') // false
m.has(262) // true
m.has(undefined) // true// set 方法返回的是当前的 Map 对象,因此可以采用链式写法。
let map = new Map().set(1, 'a').set(2, 'b').set(3, 'c')const m = new Map()
const hello = function() {console.log('hello');}
m.set(hello, 'Hello ES6!') // 键是函数
m.get(hello) // Hello ES6!const m = new Map();
m.set(undefined, 'nah')
m.has(undefined) // true
m.delete(undefined)
m.has(undefined) // falselet map = new Map()
map.set('foo', true)
map.set('bar', false)
map.size // 2
map.clear()
map.size // 0
【Map实例的遍历方法】
| 遍历方法(用于遍历成员) | 说明 |
|---|---|
| Map.prototype.keys() | 返回键名的遍历器。 |
| Map.prototype.values() | 返回键值的遍历器。 |
| Map.prototype.entries() | 返回所有成员的遍历器。 |
| Map.prototype.forEach() | 遍历 Map 的所有成员。 |
需要特别注意的是,Map 的遍历顺序就是插入顺序。
const map = new Map([['F', 'no'],['T', 'yes']
])for (let key of map.keys()) {console.log(key)
}
// F Tfor (let value of map.values()) {console.log(value)
}
// no yesfor (let item of map.entries()) {console.log(item[0], item[1])
}
// F no T yes// 或者
for (let [key, value] of map.entries()) {console.log(key, value)
}
// F no T yesmap.forEach(function(value, key, map) {console.log(value, key, map)
})
// no F Map(2) {'F' => 'no', 'T' => 'yes'}
// yes T Map(2) {'F' => 'no', 'T' => 'yes'}
Map 结构的默认遍历器接口(Symbol.iterator属性),就是 entries 方法。 这意味着,可以省略 entries 方法。
map[Symbol.iterator] === map.entrie // true// 等同于使用 map.entries()
for (let [key, value] of map) {console.log(key, value)
}
// F no T yes
3、与其他数据结构的互相转换
Map 转为数组
const map = new Map().set(true, 7).set({foo: 3}, ['abc'])[...map.keys()] // [ true, { foo: 3 } ]
[...map.values()] // [ 7, [ 'abc' ] ]
[...map.entries()] // [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]
[...map] // [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]// 转为数组后,数组的 map 和 filter 方法也可以间接用于 Map
数组 转为 Map
new Map([[true, 7],[{foo: 3}, ['abc']]
])
// Map { true => 7, Object {foo: 3} => ['abc'] }
Map 转为对象
如果所有 Map 的键都是字符串,它可以无损地转为对象。
如果有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名。
function strMapToObj(strMap) {let obj = Object.create(null)for (let [k, v] of strMap) {obj[k] = v}return obj
}const myMap = new Map().set('yes', true).set('no', false)
strMapToObj(myMap) // { yes: true, no: false }
对象转为 Map
let obj = { a: 1, b: 2 }
let map = new Map(Object.entries(obj))// 自己封装实现
function objToStrMap(obj) {let strMap = new Map()for (let k of Object.keys(obj)) {strMap.set(k, obj[k])}return strMap
}objToStrMap({yes: true, no: false}) // Map {yes => true, no => false}
4、应用
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<p>1</p>
<p>2</p>
<p>3</p>
<script>const [p1, p2, p3] = document.querySelectorAll('p')const m = new Map([[p1, {color: 'red',backgroundColor: 'yellow',fontSize: '40px'}],[p2, {color: 'green',backgroundColor: 'pink',fontSize: '40px'}],[p3, {color: 'blue',backgroundColor: 'orange',fontSize: '40px'}]]);m.forEach((propObj, elem) => {for (const p in propObj) {elem.style[p] = propObj[p];}}) // 由于不需要改变 this 指向,所以可以使用箭头函数
</script>
</body>
</html>
相关文章:
【09】ES6:Set 和 Map 数据结构
一、Set 1、基本语法 定义 Set 是一系列无序、没有重复值的数据集合。数组是一系列有序(下标索引)的数据集合。 Set 本身是一个构造函数,用来生成 Set 数据结构。 const s new Set() [2, 3, 5, 4, 5, 2, 2].forEach(x > s.add(x))fo…...
Java通过documents4j和libreoffice把word转为pdf
文章目录 word转pdf的相关第三方jar说明Linux系统安装LibreOffice在线安装离线安装word转pdf验证 Java工具类代码 word转pdf的相关第三方jar说明 docx4j 免费开源、稍微复杂点的word,样式完全乱了,且xalan升级为2.7.3后会报错。poi 免费开源、官方文档少…...
物联网时代的访问控制研究综述
A survey on Access Control in the Age of Internet of Things 文章目录 A B S T R A C T引言A. Comparison Between This Paper and Existing SurveysB. Contributions II.ACCESS CONTROL BACKGROUNDIII. ACCESS CONTROL CHALLENGES IN IOT SEARCHA. Characteristics of IoT …...
【产品经理】需求池和版本树
在这个人人都是产品经理的时代,每位入行的产品人进阶速度与到达高度各有不同。本文作者结合自身三年产品行业的经历,根据案例拆解产品行业的极简研发过程、需求池、版本树、产品自我优化等相关具体方法论。 一、产品研发的极简过程 1. 产品概述 产品就…...
Qt图像处理-OpenCv中Mat与QImage互转
Qt图像处理时需要OpenCv中Mat与QImage互转,具体代码如下 创建EditPhoto,头文件,使用前需要配置好opencv #include <QObject> #include <QImage> #include <QDebug>#include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> …...
构建外卖小程序:技术代码实践
在这个数字化的时代,外卖小程序已经成为餐饮业的一项重要工具。在本文中,我们将通过一些简单而实用的技术代码,向您展示如何构建一个基本的外卖小程序。我们将使用微信小程序平台作为例子,但这些原理同样适用于其他小程序平台。 …...
IDEA中显示方法、类注释信息
目录 一、IDEA测试版本及环境二、操作步骤2.1 鼠标悬停在某一个方法上,从而显示方法的注释信息2.2 调用方法时同步显示方法注释信息2.3 在new一个对象时,这个对象有很多重载的构造方法,想要重载的构造函数都显示出来 一、IDEA测试版本及环境 …...
《数据结构、算法与应用C++语言描述》- 堆排序 - 借助priority_queue的C++实现
堆排序 完整可编译运行代码见:Github::Data-Structures-Algorithms-and-Applications/_27HeapSort 定义 借助堆进行排序。先用n个待排序的元素初始化一个小根堆,然后从堆中逐个提取(即删除元素)元素。初始化的时间复杂度为O(n),大根堆中每…...
10.CSS浮动
CSS浮动 1.介绍 在最初,浮动是用来实现文字环绕图片效果的,现在浮动是主流的页面布局方式之一 2.作用 让元素脱离标准流,同一级的浮动的元素可以并排在一排显示 3.元素浮动后的特点 脱离文档流不管浮动前是什么元素,浮动后&…...
Angular 2 学习笔记
Angular 2 应用主要由以下 几个部分组成: 1、模块 (Modules): 2、组件 (Components): 3、模板 (Templates): 4、元数据 (Metadata): 5、数据绑定 (Data Binding) 6、指令 (Directives) 7、服务 (Servic…...
xcode 修改 target 中设备朝向崩溃
修改xcode的target中的设备朝向导致崩溃。 从日志上看好像没有什么特别的信息。 之后想了想,感觉这个应该还是跟xcode的配置有关系,不过改动的地方好像也只有plist。 就又翻腾了半天plist中的各种配置项,再把所有的用户权限提示相关的东西之…...
ZLMediaKit 编译以及测试(Centos 7.9 环境)
文章目录 一、前言二、编译器1、获取代码2、编译器2.1 编译器版本要求2.2 安装编译器 3、安装cmake4、依赖库4.1 依赖库列表4.2 安装依赖库4.2.1 安装libssl-dev和libsdl-dev4.2.2 安装 ffmpeg-devel依赖和ffmpeg依赖 三、构建和编译项目(启用WebRTC功能)…...
汽车清除积碳和清洗节气门
汽车清除积碳和清洗节气门 汽车需要清除积碳的部位检查积碳方法: 清除积碳和清洗节气门风险:燃油宝 第一次清除积碳1万公里2万公里3万公里--5万公里6万公里以上 汽车需要清除积碳的部位 节气门喷油嘴进气道燃烧室 检查积碳方法: 建议每3到5…...
RocketMQ 总体概括
目录 概述RocketMQ 领域模型MQ 解决的问题电商平台案例初步设计引入中间件设计 MQ 选型结束 概述 官网地址 RocketMQ 领域模型 官方领域模型概述 下面图,是在自己理解的基础上,对官方的模型图添加了一些。 Topic:主题,可以理解…...
使用qemu在arm上模拟x86并运行docker
背景 有一个x86的docker镜像,但是需要运行在aarch64(arm64)上,无奈只能用qemu模拟x86的架构,但是最终没有实现。 原因分析:可能是使用的server版本的ubuntu镜像,建议之后换用desktop版本的ubuntu18镜像(猜…...
IIS配置多域名跨域
搜索了一轮,自己实践发现iis中填多条Access-Control-Allow-Origin记录、逗号分隔、正则表达式这些是不行的。另外好像无论Ngxin还是Tomcat等都要rewrite之类的方法。由于仅仅是测试,所以暂时用*通配符算了。记录一下参考,要的时候再研究 CORS…...
el-form表单校验输入框值为0时 提示校验不通过
el-form表单校验输入框值为0时提示校验不通过 配置validator自定义校验方法 这里举例在结构代码里加入校验规则 <el-form-item:prop"num":rules"[{required: true,message: 请输入数量,trigger: change,},{validator,trigger: blur}]" ><el-inpu…...
Vue3后台管理-项目总结
后台管理 1. 动态路由2. 动态侧边栏菜单 持续更新中。。。 1. 动态路由 后台路由模型数据 (如果后端不知道怎么转为 这种树结构的路由,可以参考 普通数组转树结构的数组) const dynamicRoutes [{path: /,name: Layout,redirect: /home,comp…...
利用Pytorch预训练模型进行图像分类
Use Pre-trained models for Image Classification. # This post is rectified on the base of https://learnopencv.com/pytorch-for-beginners-image-classification-using-pre-trained-models/# And we have re-orginaized the code script.预训练模型(Pre-trained models)…...
MSF学习
之前的渗透测试中 其实很少用到 cs msf 但是在实际内网的时候 可以发现 msf cs 都是很好用的 所以现在我来学习一下 msf的使用方法 kali自带msf https://www.cnblogs.com/bmjoker/p/10051014.html 使用 msfconsole 启动即可 首先就是最正常的木马生成 所以这里其实只需…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构
React 实战项目:微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇!在前 29 篇文章中,我们从 React 的基础概念逐步深入到高级技巧,涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...
CppCon 2015 学习:REFLECTION TECHNIQUES IN C++
关于 Reflection(反射) 这个概念,总结一下: Reflection(反射)是什么? 反射是对类型的自我检查能力(Introspection) 可以查看类的成员变量、成员函数等信息。反射允许枚…...
