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

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

JDK 17 序列化是怎么回事

如何序列化&#xff1f;其实很简单&#xff0c;就是根据每个类型&#xff0c;用工厂类调用。逐个完成。 没什么漂亮的代码&#xff0c;只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…...