JavaScript系列(9)-- Set数据结构专题
JavaScript Set数据结构专题 🎲
在前八篇文章中,我们探讨了JavaScript的语言特性、ECMAScript标准、引擎工作原理、数值类型、字符串处理、Symbol类型、Object高级特性和Array高级操作。今天,让我们深入了解JavaScript中的Set数据结构。Set是ES6引入的一种新的集合类型,它允许你存储任何类型的唯一值。
Set基础概念 🌟
💡 小知识:Set是一个值的集合,其中的每个值只能出现一次。这个特性使它特别适合用于去重和集合运算。与Array不同,Set不是索引集合,它更关注值的唯一性。
Set的创建和基本操作 📊
// 1. Set的创建方式
function setCreation() {// 空Setconst set1 = new Set();// 从数组创建const set2 = new Set([1, 2, 3, 3, 4]); // 重复的3只会保留一个// 从字符串创建const set3 = new Set('hello'); // Set(4) {'h', 'e', 'l', 'o'}// 从其他可迭代对象创建const map = new Map([['a', 1], ['b', 2]]);const set4 = new Set(map.keys());// 基本操作set1.add(1); // 添加值set1.delete(1); // 删除值set1.has(1); // 检查值是否存在set1.clear(); // 清空Setconsole.log(set1.size); // 获取大小
}// 2. Set的迭代
function setIteration() {const set = new Set(['a', 'b', 'c']);// forEach方法set.forEach((value, valueAgain, set) => {console.log(value); // value和valueAgain是相同的});// for...of循环for (const value of set) {console.log(value);}// 转换为数组const array = [...set];const array2 = Array.from(set);// 获取迭代器const values = set.values();const entries = set.entries();// entries()返回[value, value]形式的条目for (const [value1, value2] of entries) {console.log(value1 === value2); // true}
}// 3. Set的值比较
function setValueComparison() {const set = new Set();// NaN的处理set.add(NaN);set.add(NaN);console.log(set.size); // 1,NaN被认为是相同的值// +0和-0的处理set.add(+0);set.add(-0);console.log(set.size); // 1,+0和-0被认为是相同的值// 对象的处理const obj1 = { id: 1 };const obj2 = { id: 1 };set.add(obj1);set.add(obj2);console.log(set.size); // 2,不同对象被认为是不同的值
}
Set的高级操作 🔧
// 1. 集合运算
class SetOperations {// 并集static union(setA, setB) {return new Set([...setA, ...setB]);}// 交集static intersection(setA, setB) {return new Set([...setA].filter(x => setB.has(x)));}// 差集static difference(setA, setB) {return new Set([...setA].filter(x => !setB.has(x)));}// 对称差集static symmetricDifference(setA, setB) {return new Set([...setA].filter(x => !setB.has(x)).concat([...setB].filter(x => !setA.has(x))));}// 子集检查static isSubset(setA, setB) {return [...setA].every(x => setB.has(x));}// 超集检查static isSuperset(setA, setB) {return [...setB].every(x => setA.has(x));}
}// 2. 自定义Set操作
class CustomSet extends Set {// 添加多个值addMany(...items) {items.forEach(item => this.add(item));return this;}// 删除多个值deleteMany(...items) {items.forEach(item => this.delete(item));return this;}// 过滤操作filter(callback) {const filteredSet = new CustomSet();for (const value of this) {if (callback(value)) {filteredSet.add(value);}}return filteredSet;}// 映射操作map(callback) {const mappedSet = new CustomSet();for (const value of this) {mappedSet.add(callback(value));}return mappedSet;}// 转换为对象toObject(keyFn = value => value) {const obj = {};for (const value of this) {obj[keyFn(value)] = value;}return obj;}
}// 3. Set与数组的互操作
class SetArrayOperations {// 数组去重static uniqueArray(arr) {return [...new Set(arr)];}// 查找重复元素static findDuplicates(arr) {const seen = new Set();const duplicates = new Set();arr.forEach(item => {if (seen.has(item)) {duplicates.add(item);} else {seen.add(item);}});return duplicates;}// 保持插入顺序的唯一化static uniqueOrdered(arr) {return Array.from(new Set(arr));}
}
Set的实际应用 💼
让我们看看Set在实际开发中的一些应用场景:
// 1. 标签系统
class TagSystem {constructor() {this.tagSets = new Map();}// 添加标签addTags(itemId, ...tags) {if (!this.tagSets.has(itemId)) {this.tagSets.set(itemId, new Set());}tags.forEach(tag => this.tagSets.get(itemId).add(tag));}// 移除标签removeTags(itemId, ...tags) {const tagSet = this.tagSets.get(itemId);if (tagSet) {tags.forEach(tag => tagSet.delete(tag));}}// 获取具有特定标签的项目getItemsWithTags(...tags) {const items = [];for (const [itemId, tagSet] of this.tagSets) {if (tags.every(tag => tagSet.has(tag))) {items.push(itemId);}}return items;}// 获取相关标签getRelatedTags(tag) {const relatedTags = new Set();for (const tagSet of this.tagSets.values()) {if (tagSet.has(tag)) {tagSet.forEach(t => {if (t !== tag) relatedTags.add(t);});}}return relatedTags;}
}// 2. 用户权限系统
class PermissionSystem {constructor() {this.userPermissions = new Map();this.rolePermissions = new Map();}// 添加角色权限addRolePermissions(role, ...permissions) {if (!this.rolePermissions.has(role)) {this.rolePermissions.set(role, new Set());}permissions.forEach(perm => this.rolePermissions.get(role).add(perm));}// 分配用户角色assignUserRoles(userId, ...roles) {if (!this.userPermissions.has(userId)) {this.userPermissions.set(userId, new Set());}const userPerms = this.userPermissions.get(userId);roles.forEach(role => {const rolePerms = this.rolePermissions.get(role);if (rolePerms) {rolePerms.forEach(perm => userPerms.add(perm));}});}// 检查权限hasPermission(userId, permission) {const userPerms = this.userPermissions.get(userId);return userPerms ? userPerms.has(permission) : false;}
}// 3. 缓存系统
class CacheSystem {constructor(maxSize = 1000) {this.maxSize = maxSize;this.cache = new Map();this.accessOrder = new Set();}get(key) {if (this.cache.has(key)) {// 更新访问顺序this.accessOrder.delete(key);this.accessOrder.add(key);return this.cache.get(key);}return null;}set(key, value) {if (this.cache.size >= this.maxSize && !this.cache.has(key)) {// 移除最早访问的项const oldestKey = this.accessOrder.values().next().value;this.accessOrder.delete(oldestKey);this.cache.delete(oldestKey);}this.cache.set(key, value);this.accessOrder.delete(key);this.accessOrder.add(key);}
}
性能优化 ⚡
处理Set时的一些性能优化技巧:
// 1. Set大小优化
function setSizeOptimization() {// 预分配合适的大小const initialData = new Array(1000).fill(0).map((_, i) => i);// 一次性创建Setconst set = new Set(initialData); // 比循环添加更快// 避免频繁修改const tempArray = [];for (let i = 0; i < 1000; i++) {tempArray.push(i);}const set2 = new Set(tempArray);
}// 2. Set操作优化
class OptimizedSetOperations {// 优化的交集操作static optimizedIntersection(setA, setB) {// 选择较小的集合进行迭代const [smaller, bigger] = setA.size < setB.size ? [setA, setB] : [setB, setA];return new Set([...smaller].filter(x => bigger.has(x)));}// 批量操作优化static batchAdd(set, items) {const tempSet = new Set(set);items.forEach(item => tempSet.add(item));return tempSet;}
}// 3. 内存优化
class MemoryEfficientSet {constructor() {this.set = new Set();this.weakRefs = new WeakMap();}addObject(obj) {const ref = new WeakRef(obj);this.weakRefs.set(obj, ref);this.set.add(ref);}hasObject(obj) {const ref = this.weakRefs.get(obj);return ref && this.set.has(ref) && ref.deref() === obj;}
}
最佳实践建议 💡
- Set使用场景
// 1. 数据去重
function deduplication() {// 基本类型去重const numbers = [1, 2, 2, 3, 3, 4];const uniqueNumbers = [...new Set(numbers)];// 对象去重const objects = [{ id: 1, name: 'A' },{ id: 1, name: 'A' },{ id: 2, name: 'B' }];const uniqueById = [...new Set(objects.map(obj => JSON.stringify(obj)))].map(str => JSON.parse(str));
}// 2. 集合运算
function setOperations() {const set1 = new Set([1, 2, 3]);const set2 = new Set([2, 3, 4]);// 并集const union = new Set([...set1, ...set2]);// 交集const intersection = new Set([...set1].filter(x => set2.has(x)));// 差集const difference = new Set([...set1].filter(x => !set2.has(x)));
}// 3. 唯一性检查
function uniquenessChecking() {const visited = new Set();function isUnique(item) {if (visited.has(item)) return false;visited.add(item);return true;}
}
- 错误处理和验证
// 1. Set验证
function validateSet(set) {if (!(set instanceof Set)) {throw new TypeError('参数必须是Set类型');}if (set.size === 0) {throw new Error('Set不能为空');}return true;
}// 2. 安全的Set操作
function safeSetOperations() {function safeAdd(set, value) {try {set.add(value);return true;} catch (error) {console.error('添加值失败:', error);return false;}}function safeDelete(set, value) {try {return set.delete(value);} catch (error) {console.error('删除值失败:', error);return false;}}
}// 3. 类型检查
function setTypeChecking() {function isNumberSet(set) {return set instanceof Set && [...set].every(x => typeof x === 'number');}function isObjectSet(set) {return set instanceof Set && [...set].every(x => x && typeof x === 'object');}
}
结语 📝
JavaScript的Set数据结构为我们提供了一种优雅的方式来处理唯一值的集合。我们学习了:
- Set的基本概念和操作
- Set的高级操作和扩展
- 实际应用场景
- 性能优化技巧
- 最佳实践和注意事项
💡 学习建议:在使用Set时,要充分利用其唯一性特征,选择合适的场景使用。注意Set的值比较规则,特别是在处理对象时。同时,要考虑性能影响,合理使用Set的各种操作方法。
如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇
终身学习,共同成长。
咱们下一期见
💻
相关文章:
JavaScript系列(9)-- Set数据结构专题
JavaScript Set数据结构专题 🎲 在前八篇文章中,我们探讨了JavaScript的语言特性、ECMAScript标准、引擎工作原理、数值类型、字符串处理、Symbol类型、Object高级特性和Array高级操作。今天,让我们深入了解JavaScript中的Set数据结构。Set是…...

开发培训-慧集通(iPaaS)集成平台脚本开发Groovy基础培训视频
Groovy是一种基于Java虚拟机(JVM)的敏捷开发语言,结合了Python、Ruby和Smalltalk的许多强大特性。它旨在提高开发者的生产力,通过简洁、熟悉且易于学习的语法,Groovy能够与Java代码无缝集成,并提供强大…...

【软考网工笔记】计算机基础理论与安全——网络规划与设计
HFC 混合光纤同轴电缆网 HFC: Hybrid Fiber - Coaxial 的缩写,即混合光纤同轴电缆网。是一种经济实用的综合数字服务宽带网接入技术。 HFC 通常由光纤干线、同轴电缆支线和用户配线网络三部分组成,从有线电视台出来的节目信号先变成光信号在干线上传输…...

【设计模式】 基本原则、设计模式分类
设计模式 设计模式是软件工程中的一种通用术语,指的是针对特定问题的经过实践验证的解决方案。设计模式并不是最终的代码实现,而是描述了如何解决某一类问题的思路和方法。 如果熟悉了设计模式,当遇到类似的场景,我们可以快速地…...

mac m2 安装 docker
文章目录 安装1.下载安装包2.在downloads中打开3.在启动台打开打开终端验证 修改国内镜像地址小结 安装 1.下载安装包 到官网下载适配的安装包:https://www.docker.com/products/docker-desktop/ 2.在downloads中打开 拖过去 3.在启动台打开 选择推荐设置 …...
Vue3-pinia的具体使用和刷新页面状态保持解决方案
在 Vue 3 中,Pinia 是一个官方推荐的状态管理库,它替代了 Vuex(Vuex在Vue3中依然可以正常使用),提供了更加简洁和现代的 API,同时能够与 Vue 3完美配合。在本回答中,我们将详细介绍 Pinia 的使用…...

用ResNet50+Qwen2-VL-2B-Instruct+LoRA模仿Diffusion-VLA的论文思路,在3090显卡上训练和测试成功
想一步步的实现Diffusion VLA论文的思路,不过论文的图像的输入用DINOv2进行特征提取的,我先把这个部分换成ResNet50。 老铁们,直接上代码: from PIL import Image import torch import torchvision.models as models from torch…...
创建.net core 8.0项目时,有个启用原生AOT发布是什么意思
启用原生 AOT 发布(Native AOT publishing) 是指在 .NET 6 及更高版本中使用 Ahead-of-Time (AOT) 编译 技术,将应用程序提前编译为本地机器代码,从而生成更高效、更快速启动的可执行文件。 1. AOT 编译是什么? AOT …...

2.1.7-1 io_uring的使用
一、背景 (1)下面几个有关异步操作的例子: a)客户端和服务端的异步关系,就是客户端发送请求后不需要等待结果,接下来发送其他请求。 b)对于服务端,客户端来请求后,服务…...

群论学习笔记
什么是对称? 对称是一个保持对象结构不变的变换,对称是一个过程,而不是一个具体的事物,伽罗瓦的对称是对方程根的置换,而一个置换就是对一系列事物的重排方式,严格的说,它也并不是这个重排本身…...
深入解析-正则表达式
学习正则,我们到底要学什么? 正则表达式(RegEx)是一种强大的文本匹配工具,广泛应用于数据验证、文本搜索、替换和解析等领域。学习正则表达式,我们不仅要掌握其语法规则,还需要学会如何高效地利…...

yolov5核查数据标注漏报和误报
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、误报二、漏报三、源码总结 前言 本文主要用于记录数据标注和模型预测之间的漏报和误报思想及其源码 提示:以下是本篇文章正文内容,…...

日志聚类算法 Drain 的实践与改良
在现实场景中,业务程序输出的日志往往规模庞大并且类型纷繁复杂。我们在查询和查看这些日志时,平铺的日志列表会让我们目不暇接,难以快速聚焦找到重要的日志条目。 在观测云中,我们在日志页面提供了聚类分析功能,可以…...

如何让用户在网页中填写PDF表格?
在网页中让用户直接填写PDF表格,可以大大简化填写、打印、扫描和提交表单的流程。通过使用复选框、按钮和列表等交互元素,PDF表格不仅让填写过程更高效,还能方便地在电脑或移动设备上访问和提交数据。 以下是在浏览器中显示可填写PDF表单的四…...

GXUOJ-算法-补题:22级《算法设计与分析》第一次课堂练习
2.最大子数组和 问题描述 代码解答 #include<bits/stdc.h> using namespace std; const int N1005; int sum,n,a[N]; int res-1;int result(){for(int i0;i<n;i){if(sum<0) suma[i];else{suma[i];resmax(res,sum);}}return res; } int main(){cin>>n;for(i…...
源代码编译安装X11及相关库、vim,配置vim(3)
一、vim插件安装 首先安装插件管理器Vundle ()。参照官网流程即可。vim的插件管理器有多个,只用Vundle就够了。然后~/.vimrc里写上要安装的插件: filetype offset rtp~/.vim/bundle/Vundle.vim call vundle#begin() Plugin VundleVim/Vundle.vim Plugin powerline…...

uniapp 微信小程序 自定义日历组件
效果图 功能:可以记录当天是否有某些任务或者某些记录 具体使用: 子组件代码 <template><view class"Accumulate"><view class"bx"><view class"bxx"><view class"plank"><…...

EdgeX规则引擎eKuiper
EdgeX 规则引擎eKuiper 一、架构设计 LF Edge eKuiper 是物联网数据分析和流式计算引擎。它是一个通用的边缘计算服务或中间件,为资源有限的边缘网关或设备而设计。 eKuiper 采用 Go 语言编写,其架构如下图所示: eKuiper 是 Golang 实现的轻量级物联网边缘分析、流式处理开源…...
react 优化方案
更详细的 React 优化方案可以分为性能优化、代码结构优化、开发效率提升等多个方面,结合实际项目需求,逐步应用这些优化策略。 一、性能优化 1. 避免不必要的重新渲染 React.memo: 缓存组件,防止组件在父组件重新渲染时无意义的重新渲染。 const ChildComponent = Reac…...

【Linux】sed编辑器
一、基本介绍 sed编辑器也叫流编辑器(stream editor),它是根据事先设计好得一组规则编辑数据流。 交互式文本编辑器(如Vim)中,可以用键盘命令交互式地插入、删除或替换文本数据。 sed编辑器是根据命令处理…...
hot100 -- 6.矩阵系列
1.矩阵置零 问题:给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 方法:记录行列 置0 # 记录行列,分别置0 def set_zero(matrix):row, col [], []# 统计0元素…...

音视频之视频压缩编码的基本原理
系列文章: 1、音视频之视频压缩技术及数字视频综述 2、音视频之视频压缩编码的基本原理 一、预测编码: 1、预测编码的基本概念: 预测法是最简单、实用的视频压缩编码方法,经过压缩编码后传输的并不是像素本身的取样值࿰…...
结合Jenkins、Docker和Kubernetes等主流工具,部署Spring Boot自动化实战指南
基于最佳实践的Spring Boot自动化部署实战指南,结合Jenkins、Docker和Kubernetes等主流工具,提供从环境搭建到生产部署的完整流程: 一、环境准备与工具选型 1.基础设施 Jenkins服务器:安装Jenkins LTS版本,配置JDK(推荐JDK 11+)及Maven/Gradle插…...
Linux 系统 rsyslog 配置
Linux 系统 rsyslog 配置指南 rsyslog 是 Linux 系统的下一代日志处理系统,功能强大且高效。以下是从基础到高级的全面配置指南: 1. 安装与基础配置 安装 rsyslog # Ubuntu/Debian sudo apt update sudo apt install rsyslog# CentOS/RHEL sudo yum …...
机器学习的数学基础:假设检验
假设检验 默认以错误率为性能度量,错误率由下式给出: E ( f , D ) ∫ x ∼ D I I ( f ( x ) ≠ y ) p ( x ) d x E(f,\mathcal{D})\int_{\boldsymbol{x}\sim \mathcal{D}}\mathbb{II}(f(\boldsymbol{x})\ne y )p(\boldsymbol{x})\text{d}\boldsymbol{x…...

Docker慢慢学
1、Docker DeskTop 2、N8N下载 docker run -p 8888:5678 n8nio/n8n 3、Kafka kafka依赖zookeeper,先启动zookeeper docker pull zookeeper docker run -d --name zookeeper -p 2181:2181 -e ALLOW_ANONYMOUS_LOGINyes zookeeper 启动kafka docker pull confluentinc/cp…...

【Linux】Linux 环境变量
参考博客:https://blog.csdn.net/sjsjnsjnn/article/details/125533127 一、环境变量 1.1 基本概念 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数如:我们在编写C/C代码的时候,在链接的时候&am…...

Springboot——整合websocket并根据type区别处理
文章目录 前言架构思想项目结构代码实现依赖引入自定义注解定义具体的处理类定义 TypeAWebSocketHandler定义 TypeBWebSocketHandler 定义路由处理类配置类,绑定point制定前端页面编写测试接口方便跳转进入前端页面 测试验证结语 前言 之前写过一篇类似的博客&…...

第十三节:第五部分:集合框架:集合嵌套
集合嵌套案例分析 代码: package com.itheima.day27_Collection_nesting;import java.util.*;/*目标:理解集合的嵌套。 江苏省 "南京市","扬州市","苏州市","无锡市","常州市" 湖北省 "武汉市","…...

windows编程实现文件拷贝
项目源码链接: 实现文件拷贝功能(限制5GB大小) 81c57de 周不才/cpp_linux study - Gitee.com 知识准备: 1.句柄 句柄是一个用于标识和引用系统资源(如文件、窗口、进程、线程、位图等)的值。它不是资…...