当前位置: 首页 > 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编辑器是根据命令处理…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积

1.题目介绍 给定一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O…...

【UE5 C++】通过文件对话框获取选择文件的路径

目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 &#xff0c;这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器&#xff0c;右键点击 .uproject 文件&#xff0c;选择 "Generate Visual Studio project files"&#xff0c;重…...

MySQL体系架构解析(三):MySQL目录与启动配置全解析

MySQL中的目录和文件 bin目录 在 MySQL 的安装目录下有一个特别重要的 bin 目录&#xff0c;这个目录下存放着许多可执行文件。与其他系统的可执行文件类似&#xff0c;这些可执行文件都是与服务器和客户端程序相关的。 启动MySQL服务器程序 在 UNIX 系统中&#xff0c;用…...

边缘计算网关提升水产养殖尾水处理的远程运维效率

一、项目背景 随着水产养殖行业的快速发展&#xff0c;养殖尾水的处理成为了一个亟待解决的环保问题。传统的尾水处理方式不仅效率低下&#xff0c;而且难以实现精准监控和管理。为了提升尾水处理的效果和效率&#xff0c;同时降低人力成本&#xff0c;某大型水产养殖企业决定…...

32位寻址与64位寻址

32位寻址与64位寻址 32位寻址是什么&#xff1f; 32位寻址是指计算机的CPU、内存或总线系统使用32位二进制数来标识和访问内存中的存储单元&#xff08;地址&#xff09;&#xff0c;其核心含义与能力如下&#xff1a; 1. 核心定义 地址位宽&#xff1a;CPU或内存控制器用32位…...

Spring事务传播机制有哪些?

导语&#xff1a; Spring事务传播机制是后端面试中的必考知识点&#xff0c;特别容易出现在“项目细节挖掘”阶段。面试官通过它来判断你是否真正理解事务控制的本质与异常传播机制。本文将从实战与源码角度出发&#xff0c;全面剖析Spring事务传播机制&#xff0c;帮助你答得有…...

vue3 手动封装城市三级联动

要做的功能 示意图是这样的&#xff0c;因为后端给的数据结构 不足以使用ant-design组件 的联动查询组件 所以只能自己分装 组件 当然 这个数据后端给的不一样的情况下 可能组件内对应的 逻辑方式就不一样 毕竟是 三个 数组 省份 城市 区域 我直接粘贴组件代码了 <temp…...