当前位置: 首页 > news >正文

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;}
}

最佳实践建议 💡

  1. 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. 错误处理和验证
// 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数据结构为我们提供了一种优雅的方式来处理唯一值的集合。我们学习了:

  1. Set的基本概念和操作
  2. Set的高级操作和扩展
  3. 实际应用场景
  4. 性能优化技巧
  5. 最佳实践和注意事项

💡 学习建议:在使用Set时,要充分利用其唯一性特征,选择合适的场景使用。注意Set的值比较规则,特别是在处理对象时。同时,要考虑性能影响,合理使用Set的各种操作方法。


如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻

相关文章:

JavaScript系列(9)-- Set数据结构专题

JavaScript Set数据结构专题 &#x1f3b2; 在前八篇文章中&#xff0c;我们探讨了JavaScript的语言特性、ECMAScript标准、引擎工作原理、数值类型、字符串处理、Symbol类型、Object高级特性和Array高级操作。今天&#xff0c;让我们深入了解JavaScript中的Set数据结构。Set是…...

开发培训-慧集通(iPaaS)集成平台脚本开发Groovy基础培训视频

‌Groovy‌是一种基于Java虚拟机&#xff08;JVM&#xff09;的敏捷开发语言&#xff0c;结合了Python、Ruby和Smalltalk的许多强大特性。它旨在提高开发者的生产力&#xff0c;通过简洁、熟悉且易于学习的语法&#xff0c;Groovy能够与Java代码无缝集成&#xff0c;并提供强大…...

【软考网工笔记】计算机基础理论与安全——网络规划与设计

HFC 混合光纤同轴电缆网 HFC: Hybrid Fiber - Coaxial 的缩写&#xff0c;即混合光纤同轴电缆网。是一种经济实用的综合数字服务宽带网接入技术。 HFC 通常由光纤干线、同轴电缆支线和用户配线网络三部分组成&#xff0c;从有线电视台出来的节目信号先变成光信号在干线上传输…...

【设计模式】 基本原则、设计模式分类

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

mac m2 安装 docker

文章目录 安装1.下载安装包2.在downloads中打开3.在启动台打开打开终端验证 修改国内镜像地址小结 安装 1.下载安装包 到官网下载适配的安装包&#xff1a;https://www.docker.com/products/docker-desktop/ 2.在downloads中打开 拖过去 3.在启动台打开 选择推荐设置 …...

Vue3-pinia的具体使用和刷新页面状态保持解决方案

在 Vue 3 中&#xff0c;Pinia 是一个官方推荐的状态管理库&#xff0c;它替代了 Vuex&#xff08;Vuex在Vue3中依然可以正常使用&#xff09;&#xff0c;提供了更加简洁和现代的 API&#xff0c;同时能够与 Vue 3完美配合。在本回答中&#xff0c;我们将详细介绍 Pinia 的使用…...

用ResNet50+Qwen2-VL-2B-Instruct+LoRA模仿Diffusion-VLA的论文思路,在3090显卡上训练和测试成功

想一步步的实现Diffusion VLA论文的思路&#xff0c;不过论文的图像的输入用DINOv2进行特征提取的&#xff0c;我先把这个部分换成ResNet50。 老铁们&#xff0c;直接上代码&#xff1a; from PIL import Image import torch import torchvision.models as models from torch…...

创建.net core 8.0项目时,有个启用原生AOT发布是什么意思

启用原生 AOT 发布&#xff08;Native AOT publishing&#xff09; 是指在 .NET 6 及更高版本中使用 Ahead-of-Time (AOT) 编译 技术&#xff0c;将应用程序提前编译为本地机器代码&#xff0c;从而生成更高效、更快速启动的可执行文件。 1. AOT 编译是什么&#xff1f; AOT …...

2.1.7-1 io_uring的使用

一、背景 &#xff08;1&#xff09;下面几个有关异步操作的例子&#xff1a; a&#xff09;客户端和服务端的异步关系&#xff0c;就是客户端发送请求后不需要等待结果&#xff0c;接下来发送其他请求。 b&#xff09;对于服务端&#xff0c;客户端来请求后&#xff0c;服务…...

群论学习笔记

什么是对称&#xff1f; 对称是一个保持对象结构不变的变换&#xff0c;对称是一个过程&#xff0c;而不是一个具体的事物&#xff0c;伽罗瓦的对称是对方程根的置换&#xff0c;而一个置换就是对一系列事物的重排方式&#xff0c;严格的说&#xff0c;它也并不是这个重排本身…...

深入解析-正则表达式

学习正则&#xff0c;我们到底要学什么&#xff1f; 正则表达式&#xff08;RegEx&#xff09;是一种强大的文本匹配工具&#xff0c;广泛应用于数据验证、文本搜索、替换和解析等领域。学习正则表达式&#xff0c;我们不仅要掌握其语法规则&#xff0c;还需要学会如何高效地利…...

yolov5核查数据标注漏报和误报

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

日志聚类算法 Drain 的实践与改良

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

如何让用户在网页中填写PDF表格?

在网页中让用户直接填写PDF表格&#xff0c;可以大大简化填写、打印、扫描和提交表单的流程。通过使用复选框、按钮和列表等交互元素&#xff0c;PDF表格不仅让填写过程更高效&#xff0c;还能方便地在电脑或移动设备上访问和提交数据。 以下是在浏览器中显示可填写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的插件管理器有多个&#xff0c;只用Vundle就够了。然后~/.vimrc里写上要安装的插件: filetype offset rtp~/.vim/bundle/Vundle.vim call vundle#begin() Plugin VundleVim/Vundle.vim Plugin powerline…...

uniapp 微信小程序 自定义日历组件

效果图 功能&#xff1a;可以记录当天是否有某些任务或者某些记录 具体使用&#xff1a; 子组件代码 <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编辑器也叫流编辑器&#xff08;stream editor&#xff09;&#xff0c;它是根据事先设计好得一组规则编辑数据流。 交互式文本编辑器&#xff08;如Vim&#xff09;中&#xff0c;可以用键盘命令交互式地插入、删除或替换文本数据。 sed编辑器是根据命令处理…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...