前一篇文章我们一起实现了自定义的set集合类。那么这一篇我们来给set类增加一些操作方法。那么在开始之前,还是有必要解释一下集合的操作有哪些。便于我们更快速的理解代码。

  1、并集:对于给定的两个集合,返回一个包含两个集合中所有元素的新集合。注意,集合中不会有重复的值。  

  2、交集:对于给定的两个集合,返回一个包含两个集合中共有元素的新集合。

  3、差集:对于给定的集合,返回一个包含所有存在于第一个集合且不存在于第二个集合的元素的新集合。简单来说就是我有你没有的元素。

  4、验证一个给定集合是否是另一个集合的子集。

  这里我们就不详细的再赘述一遍集合操作的数学计算方法了。有兴趣或者忘记了的小伙伴可以百度一下。那么咱们就正式开始集合的操作方法。

一、并集

//并集操作
this.union = function (otherSet) {
//存储两个集合元素的新集合,后面我们会把它作为返回值返回。
let unionSet = new Set();
//values为当前set的数组列表
let values = this.values();
//循环加入
for(let i = 0; i < values.length; i++) {
unionSet.add(values[i]);
}
//重新复制values
values = otherSet.values();
//把otherSet的值循环存入unionSet,由于我们的add不会加入重复的值,自然在unionSet中就不会出现重复的值
for(let i = 0; i < values.length; i++) {
unionSet.add(values[i]);
} return unionSet;
}

  我们发现,其实并集的操作十分简单,就是声明一个新的set,然后通过循环两个setA和setB中的值存入新的unionSet中就可以了。一点都不复杂

let setA = new Set();
setA.add(1);
setA.add(2);
setA.add(3);
let setB = new Set();
setB.add(3);
setB.add(4);
setB.add(5);
setB.add(6); let unionAB = setA.union(setB);
console.log(unionAB.values());// [1, 2, 3, 4, 5, 6]

二、交集

//交集操作
this.intersection = function (otherSet) {
let intersectionSet = new Set(); let values = this.values();
for (let i = 0; i < values.length; i++) {
if(otherSet.has(values[i])) {
intersectionSet.add(values[i])
}
} return intersectionSet;
}

  交集操作其实十分简单,一句话就是检查setA中的元素是否在setB中也有,如果有那么久存入intersectionSet中。就跟我们要查找两个数组中是否有相同的元素是一个道理。

let setC = new Set();
setC.add(5);
setC.add(6);
setC.add(7); let setD = new Set();
setD.add(5);
setD.add(7);
setD.add(4);
setD.add(8); let intersectionSetCD = setC.intersection(setD);
console.log(intersectionSetCD.values());//[5,7]

三、差集

//差集操作
this.difference = function (otherSet) {
let differenceSet = new Set(); let values = this.values();
for (let i = 0; i < values.length; i++) {
//只是比交集操作这里的判断改成了非(!)而已
if(!otherSet.has(values[i])) {
differenceSet.add(values[i])
}
} return differenceSet;
}

  差集的操作和并集的操作十分类似。并集是需要两个集合中都存在的元素(你有我也有),而差集是存在于setA中但是不存在于setB中(你有我没有)。

  所以我们只需要稍微更改一下交集的代码就可以了。

let setM = new Set();
setM.add(5);
setM.add(6);
setM.add(7); let setN = new Set();
setN.add(5);
setN.add(7);
setN.add(4);
setN.add(8); let differenceSetMN = setM.difference(setN);
console.log(differenceSetMN.values());//[6]

四、子集

//子集操作
this.subset = function (otherSet) {
if(this.size() > otherSet.size()) {
return false;
} else {
let values = this.values();
for (let i = 0; i < values.length; i++) {
if(!otherSet.has(values[i])) {
return false;
}
}
return true;
}
}

  其实子集操作也没什么好解释的,只是要注意的是如果setA的子集是setB,那么setA的元素个数是一定大于或等于setB的。否则setB就不可能是setA的子集。所以我们在最开始就判断元素的size是否符合这个定义。

  那么如果符合,我们在遍历整个setB的元素,判断在setA中是否存在,只要有不存在的就直接返回false,如果遍历结束都存在,那么才返回true。

let setX = new Set();
setX.add(1);
setX.add(2); let setY= new Set();
setY.add(1);
setY.add(2);
setY.add(3); let setZ= new Set();
setZ.add(2);
setZ.add(3);
setZ.add(4); console.log(setX.subset(setY));//true
console.log(setX.subset(setZ));//false

  这里我们就介绍完了集合的操作,是不是十分简单。那么接下来我们来看看ES6原生的set类是什么样子的。

ES6原生Set类

  我们先来看看原生set类的简单例子:

let set = new Set();
set.add(1);
console.log(set.values());//SetIterator {1}
set.add(2);
console.log(set.has(1));//true
console.log(set.size)//2
console.log(set.delete(1));//true
console.log(set.size)//1
console.log(set.has(1));//false
console.log(set.has(2));//true

  原生Set类拥有has()、add()、delete()、clear()等方法。也拥有values()、keys()、entries()、forEach()等遍历方法,还拥有一个size属性。这里不会详细的介绍每一个属性方法,想要深入学习大家可以自行去查阅。

  那么我们看看如何用原生Set类来操作集合。

let setA = new Set();
setA.add(1);
setA.add(2);
setA.add(3); let setB = new Set();
setB.add(2);
setB.add(3);
setB.add(4); //模拟并集操作
let unionAb = new Set();
//其实跟我们自定义并集操作的原理是一样的,分别遍历两个集合并把其元素加入到unionAb中
//for...of 这种操作也是ES6的循环遍历方法。
for (let x of setA) unionAb.add(x);
for (let x of setB) unionAb.add(x);
console.log(unionAb.values())//SetIterator {1, 2, 3, 4} //模拟交集操作
//模拟交集操作需要创建一个辅助函数,来生成包含setA和setB都有的元素的新集合。
let intersetion = function (setA,setB) {
let intersetionSet = new Set(); for(let x of setA) {
if(setB.has(x)) {
intersetionSet.add(x);
}
} return intersetionSet;
} let intersetionAb = intersetion(setA,setB);
console.log(intersetionAb.values())//SetIterator {2, 3} //模拟差集操作
//同样的,跟交集操作极为类似,只是判断条件刚好相反罢了
let difference = function (setA,setB) {
let differenceSet = new Set(); for(let x of setA) {
if(!setB.has(x)) {
differenceSet.add(x);
}
} return differenceSet;
} let differenceAb = difference(setA,setB);
console.log(differenceAb.values())//SetIterator {1}

  在写完了ES6原生Set类模拟集合操作的时候,我们发现跟我们自定义的集合操作方法极为相似。只是我们使用了ES6原生的接口罢了。大家可以尝试着对比一下这两种类型的代码。加深印象。

  到这里集合就介绍完毕了。回顾一下代码,我们发现其实集合的各种操作方法在我们的实际工作中也是经常应用到的,只是我们在用数组操作,并没有十分的去注意这些细节。比如并集操作,我们在合并两个数组的时候肯定用到过。比如交集操作,我们在查找两个数组中公共元素的时候就会用到。所以其实我们在工作中已经用过或者说经常使用这些类似于集合操作的思想。

  

  最后,由于本人水平有限,能力与大神仍相差甚远,若有错误或不明之处,还望大家不吝赐教指正。非常感谢!

用js来实现那些数据结构10(集合02-集合的操作)的更多相关文章

  1. 用js来实现那些数据结构—目录

    首先,有一点要声明,下面所有文章的所有内容的代码,都不是我一个人独立完成的,它们来自于一本叫做<学习JavaScript数据结构和算法>(第二版),人民邮电出版社出版的这本书.github ...

  2. 用js来实现那些数据结构及算法—目录

    首先,有一点要声明,下面所有文章的所有内容的代码,都不是我一个人独立完成的,它们来自于一本叫做<学习JavaScript数据结构和算法>(第二版),人民邮电出版社出版的这本书.github ...

  3. 用js来实现那些数据结构09(集合01-集合的实现)

    说到集合,第一个想到的就是中学学到的那个数学概念:集合.在我们开始集合相关的js实现前,我们有必要来了解一下什么是集合以及集合的数学概念. 好吧,我们一起来复习一下早就被我们遗忘的集合. 集合是由一组 ...

  4. 第10讲-Java集合框架

    第10讲 Java集合框架 1.知识点 1.1.课程回顾 1.2.本章重点 1.2.1 List 1.2.2 Set 1.2.3 Map 2.具体内容 2.1.Java集合框架 2.1.1 为什么需要 ...

  5. js前台取用后台传递过来的map集合方式

    在处理有些特殊需求的时候,我们需要在前台页面的js中获取后台传递过来的map集合类型的参数,并且进行调用,代码如下: 在后台我们拼装出如下的集合: Map<String,Grade> gr ...

  6. (js描述的)数据结构 [数组的一些补充](1)

    (js描述的)数据结构 [数组的一些补充](1) 1. js的数组: 1.优点:高度封装,对于数组的操作就是调用API 2.普通语言的数组: 1.优点:根据index来查询,修改数据效率很高 2.缺点 ...

  7. D3.js的基础部分之数组的处理 集合(Set)(v3版本)

    数组的处理 之 集合(set) 集合(Set)是数学中常用的概念,表示具有某种特定性质的事物的总体.集合里的项叫做元素.集合的相关方法有:   d3.set([array]) //使用数组来构建集合, ...

  8. [集合]Collection集合框架源码分析

    Collection接口 在java的集合类库中,基本接口是Collection,该接口的在集合中的源码定义如下(将源码中的注释删掉了): public interface Collection< ...

  9. Java 集合学习--集合概述

    一.集合框架 集合,通常也叫容器,java中有多种方式保存对象,集合是java保存对象(对象的引用)的方式之一,之前学习的数组是保存对象的最有效的方式,但是数组却存在一个缺陷,数组的大小是固定的,但是 ...

随机推荐

  1. Struts2学习笔记四 OGNL

    OGNL,全称为Object-Graph Navigation Language(对象图表达语言),它是一个功能强大的表达式语言,用来获取和设置Java对象的属性,调用java对象的方法,同时能够自动 ...

  2. js中的类型转换

    先介绍一下 typeof 的使用方法: typeof(mix)   或者  typeof  mix 其中 mix 可以是任何数据类型 typeof 的返回值有六种:number.string.bool ...

  3. JavaScript(第三十一天)【JSON】

    前两章我们探讨了XML的结构化数据,但开发人员还是觉得这种微型的数据结构还是过于烦琐.冗长.为了解决这个问题,JSON的结构化数据出现了.JSON是JavaScript的一个严格的子集,利用JavaS ...

  4. sql with as 用法-Z

    以下内容转自:http:.com/ 一.WITH AS的含义 WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会被整个 ...

  5. Java 多线程 从无到有

    个人总结:望对屏幕对面的您有所帮助 一. 线程概述 进程: 有独立的内存控件和系统资源 应用程序的执行实例 启动当前电脑任务管理器:taskmgr 进程是程序(任务)的执行过程,它持有资源(共享内存, ...

  6. Mego(2) - NET主流ORM框架分析

    接上文我们测试了各个ORM框架的性能,大家可以很直观的看到各个ORM框架与原生的ADO.NET在境删改查的性能差异.这里和大家分享下我对ORM框架的理解及一些使用经验. ORM框架工作原理 典型ORM ...

  7. cv2.cornerHarris()详解 python+OpenCV 中的 Harris 角点检测

    参考文献----------OpenCV-Python-Toturial-中文版.pdf 参考博客----------http://www.bubuko.com/infodetail-2498014. ...

  8. SQL字符串操作汇总

    SQL字符串操作汇总 --将字符串中从某个字符开始截取一段字符,然后将另外一个字符串插入此处 select stuff('hello,world!',4,4,'****')   --返回值hel*** ...

  9. Django中自定义过滤器的使用

    我在这里做的是: 从数据库查出id递增的一些信息,展示在前台. 编写一个过滤器判断查出数据的id是偶数的返回True 奇数返回False 1 创建项目,创建应用,注册应用,配置settings.py文 ...

  10. JS笔记(一)

    第一章: 编写JS流程: 1.  布局:HTML和CSS 2.  样式:修改页面元素样式,div的display样式 3.  事件:确定用户做什么操作,onclick(鼠标点击事件).onmouseo ...