ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用

字典和集合

一文了解集合和字典在前端中的应用

  • 一、📝集合
    • 1、集合是什么?
    • 2、前端与集合:使用ES6中的Set
    • 3、用Set模拟并集、交集和差集
      • (1)模拟并集运算
      • (2)模拟交集运算
      • (3)模拟差集运算
    • 4、使用扩展运算符来模拟并集、交集和差集
      • (1)用扩展运算符实现并集
      • (2)用扩展运算符实现交集
      • (3)用扩展运算符实现差集
    • 5、leetcode案例题分析
      • (1)leetcode349两个数组的交集
  • 二、📂字典
    • 1、字典是什么?
    • 2、前端与集合:使用ES6中的Map
    • 3、使用Map类的API
    • 4、leetcode案例题分析
      • (1)leetcode349两个数组的交集
      • (2)leetcode20有效地括号
      • (3)leetcode1两数之和
      • (4)leetcode3无重复字符的最长子串
      • (5)leetcode76最小覆盖子串
  • 三、📆结束语

在前端日新月异的大背景下, ES6 也基本已经覆盖性地全民普及。而数据结构集合和字典,也被运用于 ES6 的语法当中。 ES6 通过使用 SetMap 这两个函数,来实现集合和字典的思想。而集合和字典,又是怎么被灵活应用的呢?

下面的这篇文章中,将带领大家来一起了解集合和字典在前端中应用,并使用 MapSet 来实现前端的一些常见场景。一起来学习吧~🙋‍♀️

一、📝集合

1、集合是什么?

  • 集合是一种无序且唯一的数据结构;
  • ES6 中有集合,名为 Set
  • 集合的常用操作: 去重、判断某元素是否在集合中、求交集……

2、前端与集合:使用ES6中的Set

ES6 中的 Set 可以做什么呢?

  • 使用 Set 对象: newadddeletehassize
  • 迭代 Set :多种迭代方法、 SetArray 互转、求并集/交集/差集

3、用Set模拟并集、交集和差集

(1)模拟并集运算

我们可以创建一个函数,来返回包含 setAsetB 中所有元素的新集合。迭代这两个集合,并把所有元素都添加到并集的集合中。如下代码所示:

//模拟并集运算
const union = (setAe, setB) => {const unionab = new Set()setA.forEach(value => unionab.add(value))setB.forEach(value => unionab.add(value))return [...unionab]
}console.log(union([1, 2, 5, 8, 9], [4, 5, 8, 9, 10])) //[1, 2, 5, 8,9, 4, 10]

(2)模拟交集运算

模拟交集运算需要创建一个辅助函数,来生成包含 setAsetB 两个集合中共同拥有元素的新集合。具体代码如下:

// 模拟交集运算
const intersection = (setA, setB) => {const intersectionSet = new Set()const arrSetB = new Set(setB)setA.forEach(value => {if (arrSetB.has(value)) {intersectionSet.add(value)}})return [...intersectionSet]
}console.log(intersection([1, 2, 5, 8, 9], [4, 5, 8, 9, 10])) //[5,8,9]

(3)模拟差集运算

差集运算是创建集合 setA 有,而集合 setB 没有的元素。简单来说,就是 setA 减去和 setB 相交的部分,剩余的部分即是差集的部分。

// 模拟差集运算
const difference = (setA, setB) => {const differenceSet = new Set()const arrSetB = new Set(setB)setA.forEach(value => {if (!arrSetB.has(value)) {differenceSet.add(value)}})return [...differenceSet]
}console.log(difference([1, 2, 5, 8, 9], [4, 5, 8, 9, 10])) //[1, 2]

4、使用扩展运算符来模拟并集、交集和差集

上面我们实现了用Set来模拟并集、交集和差集,但这似乎有一点点冗余,如果遇到数据量大的时候还每一次都要执行这么多行代码,似乎这样子听起来就那么友好了。

因此,我们引入了一种新的方法来解决,ES6的扩展运算符

如果使用扩展运算符来进行运算的话,整个过程只需要三个步骤:

  • 将集合转化为数组;
  • 执行需要的运算;
  • 将结果转化回集合。

接下来我们就用扩展运算符,来一一实现并集、交集和差集

(1)用扩展运算符实现并集

来看下面一段代码:

// 模拟并集运算
const union = (setA, setB) => {return new Set([...setA, ...setB]);
}
console.log(union([1, 2, 5, 8, 9], [4, 5, 8, 9, 10])) //[1, 2, 5, 8,9, 4, 10]

通过以上代码我们可以看到,使用扩展运算符,只需要短短一行代码,即可实现具体的并集运算,这样看起来简洁了许多。

接下来我们继续用这种方法,来实现交集差集

(2)用扩展运算符实现交集

// 模拟交集运算
const intersection = (setA, setB) => {const arrB = new Set(setB);return [...new Set([...setA].filter(x => arrB.has(x)))]
}
console.log(intersection([1, 2, 5, 8, 9], [4, 5, 8, 9, 10])) //[5, 8, 9]

与并集一样的效果,运用扩展运算符,很简洁的就实现了交集的功能。

(3)用扩展运算符实现差集

// 模拟差集运算
const difference = (setA, setB) => {const arrB = new Set(setB)return [...new Set([...setA].filter(x => !arrB.has(x)))]
}
console.log(difference([1, 2, 5, 8, 9], [4, 5, 8, 9, 10])) //[1, 2]

同样地,使用扩展运算符的方法,但与交集相反的是,交集是筛选出集合setB拥有的元素,而差集是筛选出集合setB没有的元素,从而最终达到具体效果。

5、leetcode案例题分析

(1)leetcode349两个数组的交集

1)题意

这里附上原题链接

给定两个数组,编写一个函数来计算它们的交集。

输入输出示例:

  • 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
  • 输出: [9,4]
  • 解释:
    • nums1nums2 两个数组的相交部分为 [9, 4] 。

2)解题思路

  • 求交集且无序唯一。
  • 使用集合。

3)解题步骤

  • 用集合对 nums1 去重。
  • 遍历 nums1 ,筛选出 nums2 中也包含的值。

4)代码实现

/*** @param {Array} nums1 数组1* @param {Array} nums2 数组2* @returns */
let intersection = function(nums1, nums2){// 先进行数组去重const arr1 = new Set(nums1);const arr2 = new Set(nums2);// 过滤掉arr1在arr2中已经有的元素,过滤结果即为交集// has可改为includesconst arr3 = [...arr1].filter(item => arr2.has(item));return arr3;
}
console.log(intersection([1,2,3,4],[4,6,8]))

二、📂字典

1、字典是什么?

  • 字典与集合相似,字典也是一种存储唯一值的数据结构,但它是以键值对的形式来存储。
  • 注意:字典一定是以键值对的形式存储!!

2、前端与集合:使用ES6中的Map

ES6中的Map可以做什么呢?

  • 使用 Map 对象: newsetdeleteclear
  • 字典的常用操作,键值对的增删改查

3、使用Map类的API

下面展示一段代码,来展示 map 的相关 API

const map = new Map()//增
map.set('monday', '星期一')
map.set('Tuesday', '星期二')
map.set('Wednesday', '星期三')console.log(map.has('monday')) //true
console.log(map.size) //3
console.log(map.keys()) //输出{'monday', 'Tuesday', 'Wednesday'}
console.log(map.values()) //输出{'星期一', '星期二', '星期三'}
console.log(map.get('monday')) //星期一//删
map.delete('monday')//清空
map.clear()//改
map.set('monday', '星期四')

4、leetcode案例题分析

(1)leetcode349两个数组的交集

1)题意

这里附上原题链接

给定两个数组,编写一个函数来计算它们的交集。

输入输出示例:

  • 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
  • 输出: [9,4]
  • 解释:
    • nums1nums2 两个数组的相交部分为 [9, 4] 。

2)解题思路

  • nums1nums2 都有的值。
  • 字典建立一个映射关系,记录 nums1 里有的值。
  • 遍历 nums2 ,找出 nums1 里也有的值。

3)解题步骤

  • 新建一个字典,遍历 nums1 ,填充字典
  • 遍历 nums2 ,遇到字典里的值就选出,并从字典中删除。

4)代码实现

/*** @param {Array} nums1 数组1* @param {Array} nums2 数组2* @returns */
let intersection = function(nums1, nums2){// 先建立一个字典const map = new Map();// 遍历nums1的每一个,并放入数组中nums1.forEach(n => {map.set(n, true);});const res = [];// 遍历nums2中的每一个nums2.forEach(n => {// 与nums1中的对比,如果一样则push进resif(map.get(n)){res.push(n);map.delete(n);}});return res;
}console.log(intersection([1, 2, 2, 1], [2, 2]))

(2)leetcode20有效地括号

1)题意

这里附上原题链接

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

输入输出示例:

  • 输入: s = “()[]{}”
  • 输出: true
  • 解释:
    • 左括号和右括号对应开闭。

2)解题步骤

  • 判断字符串的个数是否为偶数,不是则直接返回。
  • 建立一个字典,分别将三个括号映射进入。
  • 遍历字符串
  • 遍历 nums1 ,筛选出 nums2 中也包含的值。

3)代码实现

/*** * @param {String} s 括号字符串* @returns boolean*/let isValid = function(s){if(s.length % 2 === 1){return false;}const stack = [];const map = new Map();map.set('(', ')');map.set('{', '}');map.set('[', ']');for(let i = 0; i < s.length; i++){const c = s[i];if(map.has(c)){stack.push(c);}else{// 获取栈中最后一个括号的值const t = stack[stack.length - 1];if(map.get(t) === c){stack.pop();}else{return false;}}}return stack.length === 0;
}console.log(isValid('[]')) //true
console.log(isValid('(]')) //false
console.log(isValid('([)]')) //false

(3)leetcode1两数之和

1)题意

这里附上原题链接

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那两个整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

输入输出示例:

  • 输入: nums = [2,7,11,15], target = 9
  • 输出: [0,1]
  • 解释:
    • 因为 nums[0] + nums[1] == 9 ,返回 [0, 1]

2)解题思路

  • nums 想象成相亲者;
  • target 想象成匹配条件;
  • 用字典建立一个婚姻介绍所,存储相亲者的数字和下标。

3)解题步骤

  • 新建一个字典作为婚姻介绍所;
  • nums 的值,逐个来介绍所找的对象,没有合适的就先登记,有合适的就牵手成功;
  • 键值对,键 key 代表此对象的值,值 value 代表对象的联系方式,即下标。

4)代码实现

/*** * @param {Array} nums 数组* @param {Number} target 目标和 * @returns []*/
let twoSum = function(nums, target){const map = new Map();for(i = 0; i < nums.length; i++){// 来找对象的人的值const n = nums[i];// 想找的目标对象的值const n2 = target - n;// 找到对象时if(map.has(n2)){return [map.get(n2), i];}// 找不到对象时,放进字典里等待对象的到来else{map.set(n, i);}}return '没有目标匹配';
}console.log(twoSum([1, 2, 3, 4], 6)) //[1, 3]

(4)leetcode3无重复字符的最长子串

1)题意

这里附上原题链接

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

输入输出示例:

  • 输入: s = “abcabcbb”

  • 输出: 3

  • 解释:

    • 因为无重复字符的最长子串是 "abc" ,所以其长度为 3
  • 2)解题思路

    • 先找出所有的不包含重复字符的子串。
    • 找出长度最大的那个子串,返回其长度即可。

    3)解题步骤

    • 用双指针维护一个滑动窗口,用来剪切子串
    • 不断移动右指针,遇到重复字符,就把左指针移动到重复字符的下一位。
    • 过程中,记录所有窗口的长度,并返回最大值

4)代码实现

/*** @param {string} s* @return {number}*/
let lengthOfLongestSubstring = function(s){let l = 0;let res = 0;const map = new Map();for(let r = 0; r < s.length; r++){// map.get(r) >= l 确保下标在左指针右边if(map.has(s[r]) && map.get(s[r]) >= l){l = map.get(s[r]) + 1;}res = Math.max(res, r - l + 1);map.set(s[r], r);}return res;
}console.log(lengthOfLongestSubstring('ssdfsf')) // 3

(5)leetcode76最小覆盖子串

1)题意

这里附上原题链接

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 ""

**注意:**如果 s 中存在这样的子串,我们保证它是唯一的答案。

输入输出示例:

  • 输入: s = “ADOBECODEBANC”, t = “ABC”
  • 输出: “BANC”
  • 解释:
    • BANC 覆盖 ABC 三个字母,并且是最小子串

2)解题思路

  • 先找出所有包含 T 的子串。
  • 找出长度最小的那个子串,返回即可。

3)解题步骤

  • 双指针维护一个滑动窗口。
  • 移动右指针,找到包含 T 的子串,移动左指针,尽量减少包含 T 的子串的长度。

4)代码实现

/*** @param {string} s* @param {string} t* @return {string}*/
let minWindow = function(s, t){// 用双指针维护一个滑动窗口// 指针初始位置都在第一个位置,即下标索引为0let l = 0;let r = 0;// 建立一个字典,用来表示子串需要的字符以及它的个数const need = new Map();for(let c of t){// 遍历子串的字符,存放到字典里need.set(c, need.has(c) ? need.get(c) + 1 : 1);}// 需要的类型数量let needType = need.size;let res = '';// 移动右指针while(r < s.length){// 在右指针不断移动的过程中,我们不断获取当前的字符const c = s[r];// 判断当前字符是否在我们的需求列表里面if(need.has(c)){need.set(c, need.get(c) - 1);if (need.get(c) === 0){needType -= 1;}}while(needType === 0){// 打印滑动窗口及表示的子串// substring方法遵循左闭右开原则// console.log(s.substring(l, r + 1));const newRes = s.substring(l, r + 1);// 找出最小的子串if(!res || newRes.length < res.length){res = newRes;}// c2代表左指针当前的字符const c2 = s[l];// 如果左指针在需求列表里面if(need.has(c2)){// 字符的需求数量就需要增加need.set(c2, need.get(c2) + 1);// 如果字符需求数量为1,原来是0,现在是1,那么就重新需要此字符if (need.get(c2) === 1){needType += 1;}}l += 1;}//当跳出while循环时,意味着左指针不能再移动,要开始移动右指针// 右指针移动则递增1r += 1;}return res;
}console.log(minWindow('ASDFFGFGCX','AFG')) // ASDFFG

三、📆结束语

字典和集合可以算是前端面试的必考题了,同时在日常开发中的使用频率也相对较高,因此掌握字典和集合的内容是较为重要的。

关于字典和集合在前端中的应用就讲到这里啦!希望对大家有帮助!

  • 关注公众号 星期一研究室 ,第一时间关注学习干货,更多精彩专栏待你解锁~
  • 如果这篇文章对你有用,记得 一键三连 再走哦~
  • 不期而遇,我们下期见!🥂🥂🥂

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/307954.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode383. 赎金信(两种做法)

一&#xff1a;题目 二:上码 1:第一种方法 class Solution { public:bool canConstruct(string ransomNote, string magazine) {unordered_map<char,int>m,m1;for(int j 0; j < magazine.size(); j) {m[magazine[j]];}for(int i 0; i < ransomNote.size(); i) …

使用BeetleX在Linux下部署.NET多站点服务

在windows下常用IIS来部署.NET的多站点服务&#xff0c;但在Linux下就没这么方便了&#xff1b;虽然可以使用一些代理服务器如nginx&#xff0c;jexus等来反代或部署应用&#xff0c;但nginx对.NET应用的托管就相对没这么方便了&#xff0c;jexus的确是个不错的服务应用;在这里…

模块化妙用!用vue3实现一个鼠标追踪器和异步加载组件

用vue3实现一个鼠标追踪器和异步加载组件一、&#x1f5b1;️鼠标追踪器1、功能实现2、给静态页面绑定功能二、⚙️异步加载组件1、功能实现2、给静态页面绑定功能3、用泛型改造异步组件功能三、&#x1f4da;结束语周一最近学完 vue3 新特性&#xff0c;就想着用 vue3 来捣鼓…

leetcode15. 三数之和(三指针)

一:题目 二:思路 1.这里的去重是指的是我们在遍历元素的时候&#xff0c;遇到相同的挨着的相同的元素的时候要跳过 2.对元素进行排序&#xff0c;为了后面的比较 3.我们用的是三个指针&#xff0c;第一个指针i指向第一个元素&#xff0c;第二个指针left指向第二个元素,第三个指…

vue3的传送门teleport究竟有多神奇?suspense发起异步请求有多简约?

一文讲解vue3的Teleport和Suspense一、&#x1f44b;用teleport实现打开模态框操作1、teleport是什么2、实现模态框功能&#xff08;1&#xff09;设置锚点&#xff08;2&#xff09;定义子组件&#xff08;3&#xff09;定义父组件二、&#x1f91a;用Suspense1、Suspense是什…

【BCVP】实现基于 Redis 的消息队列

聆听自己的声音如果自己学不动了&#xff0c;或者感觉没有动力的时候&#xff0c;看看书&#xff0c;听听音乐&#xff0c;跑跑步&#xff0c;休息两天&#xff0c;重新出发&#xff0c;偷懒虽好&#xff0c;可不要贪杯。话说上回书我们说到了&#xff0c;Redis的使用修改《【B…

leetcode18. 四数之和(双指针)

一&#xff1a;题目 二&#xff1a;上码 class Solution { public:vector<vector<int>> fourSum(vector<int>& nums, int target) {vector<vector<int> >ans;vector<int> v;sort(nums.begin(),nums.end());for(int i 0; i < nums…

过去3个多月的1200个小时里,我收获了什么?| 2021年年中总结

&#x1f55b;序言 今年三月初&#xff0c;善后了上学期事情之后&#xff0c;我开始在想&#xff0c;我的未来规划。 身边的好朋友和同学都在筹划着自己的未来&#xff0c;考研的考研&#xff0c;考公的考公。父母和老师们也在劝我说考研&#xff0c;问我考不考研。 依稀记得…

WPF 消息框 TextBox 绑定新数据时让光标和滚动条跳到最下面

WPF 消息框 TextBox 绑定新数据时让光标和滚动条跳到最下面独立观察员 2020 年 9 月 3 日我们在使用 WPF 的 TextBox 作为消息展示框时&#xff0c;如果想在出现滚动条之后&#xff0c;新消息到来时还能够被看到&#xff0c;也就是说让滚动条始终在最下面&#xff0c;或者说光标…

leedcode344. 反转字符串

一:题目 二:上码 class Solution { public:void reverseString(vector<char>& s) {//双指针for(int i 0,j s.size() - 1; i < s.size()/2; i,j--) {swap(s[i],s[j]);}} };

组件库实战 | 用vue3+ts实现全局Header和列表数据渲染ColumnList

用vue3ts实现全局Header和列表数据渲染ColumnList&#x1f5bc;️序言&#x1f4fb;一、ColumnList数据渲染1、设计稿抢先知2、数据构思3、视图数据绑定4、数据传递5、挠头情况☎️二、GlobalHeader全局Header1、设计稿抢先看2、数据构思3、视图数据绑定4、数据传递&#x1f4f…

初识ABP vNext(8):ABP特征管理

点击上方蓝字"小黑在哪里"关注我吧定义特征应用特征用户数量社交登录前言上一篇提到了ABP功能管理&#xff08;特征管理&#xff09;&#xff0c;它来自ABP的FeatureManagement模块&#xff0c;ABP官方文档貌似还没有这个模块的相关说明&#xff0c;但是个人感觉这个…

.NET Core 中导入导出Excel

操作Excel是一个比较常见的业务场景&#xff0c;本篇将使用EPPlus简单演示一个导入导出的示例。EPPlus开源地址&#xff1a;https://github.com/EPPlusSoftware/EPPlus在项目中添加EPPlus组件Install-Package EPPlus导入先准备一个Excel文件&#xff0c;将其内容读取出来&#…

不会webpack的前端可能是捡来的,万字总结webpack的超入门核心知识

一文了解webpack入门核心知识&#x1f3a8;序言&#x1f4c5;一、webpack究竟是什么1、写在前面2、什么是模块打包工具&#xff1f;&#x1f4d0;二、如何用Webpack搭建环境1、安装node2、创建项目3、初始化项目4、安装webpack5、安装具体版本的webpack⚙️三、Webpack的配置文…

剑指 Offer 05. 替换空格(两种做法)

一:题目 二:上码 1:方法一 class Solution { public:string replaceSpace(string s) {string str "";for(int i 0; i < s.size(); i) {if(s[i] ){str "%20";}else{str s[i];}}return str;} };2:方法二&#xff08;双指针&#xff09; class So…

.NET Core 中生成验证码

在开发中&#xff0c;有时候生成验证码的场景目前还是存在的&#xff0c;本篇演示不依赖第三方组件&#xff0c;生成随机验证码图片。先添加验证码接口public interface ICaptcha {/// <summary>/// 生成随机验证码/// </summary>/// <param name"codeLeng…

10分钟手把手教你用Android手撸一个简易的个人记账App

用Android手撸一个简易的个人记账系统⛱️序言&#x1f4cb;一、系统结构设计Design1. 需求分析2. 数据库设计3. 界面设计4. 过程设计&#x1f4d8;二、编码阶段Coding1. 项目结构&#x1f5c2;️&#xff08;1&#xff09;文件目录&#xff08;2&#xff09;AndroidManifest.x…

像素级调整,高效转换——轻松提升你的图片处理体验!

探索更高级的图片处理体验&#xff0c;我们为你带来像素级调整与高效转换的完美结合&#xff01;借助我们的专业工具&#xff0c;轻松调整图片像素&#xff0c;让你在细节处展现无限创意&#xff0c;提升作品质感。 第一步&#xff0c;进入首助编辑高手主页面&#xff0c;可以看…

ABP VNext实践之搭建可用于生产的IdentityServer4

一、前言用了半年多的abp vnext&#xff0c;在开发的效果还是非常的好&#xff0c;可以说节省了很多时间&#xff0c;像事件总线、模块化开发、动态API进行远程调用、自动API控制器等等&#xff0c;一整套的规范&#xff0c;让开发人员更方便的集成&#xff0c;提升效率&#x…

151. 翻转字符串里的单词(思路+详解)

一:题目 二:上码 class Solution { public://利用双指针使除去多余的空格,定义快慢指针&#xff0c;最后满指针指向的位置就是除去冗余空格后的字符串//大小void removespacing(string& s){int slowIndex 0,fastIndex 0;//去掉字符串前面的字符while(s.size() > 0 &a…