集合结构
-
几乎每种编程语言中,都有集合结构.
-
集合比较常见的实现方式是哈希表,我们这里来实现一个封装的集合类
-
集合通常是由一组无序的,不能重复的元素构成
- 和数学中的集合名词比较相似,但是数学中的集合范围更大一些, 也允许集合中的元素重复
- 在计算机中,集合通常表示的结构中元素是不允许重复的.
-
特殊的数组
- 特殊之处在于里面的元素没有顺序,也不能重复.
- 没有顺序意味着不能通过下标值进行访问,不能重复意味着相同的对象在集合中只会存在一份.
-
封装一个集合类.
- 2011年6月份发布的ES5中已经包含了Array类
- 2015年6月份发布的ES6中包含了Set类,所以其实我们可以不封装,直接使用它.
- 但是这里,为了明确集合的内部实现机制,我们这里还是自己来封装一下这个Set类.
// 封装集合类
function Set() {
// 属性
this.items = {}
// 方法
}
代码解析:
- 代码就是封装了一个集合的构造函数.
- 在集合中,添加了一个items属性,用于保存之后添加到集合中的元素因为Object的keys本身就是一个集合
- 后面我们给集合添加对应的操作方法.
集合的常见操作
集合有哪些常见的操作方法呢?
- add(value) :向集合添加个新的项。
- remove(value) :从集合移除一个值。
- has(value) :如果值在集合中,返回true,否则返回false.
- clear() :移除集合中的所有项。
- size() :返回集合所包含元素的数量。与数组的length属性类似。
- values() :返回个包含集合中所有值的数组。
- 还有些集合其他相关的操作,暂时用不太多,这里暂不封装.
我们来一个个实现这些方法,相对都比较简单.
// 封装集合类
function Set() {
// 属性
this.items = {}
// 方法
// add方法
Set.prototype.add = value => {
//判断当前集合中是否已经包含了该元素
if (this.has(value)) return false
// 将元素添加到集合中
this.items[value] = value
return true
}
// has方法
Set.prototype.has = value => {
return this.items.hasOwnProperty(value)
}
// remove方法
Set.prototype.remove = value => {
// 1.判断当前集合中是否已经包含了该元素
if (!this.has(value)) return false
// 2.将元素从属性中删除
delete this.items[value]
return true
}
// clear方法
Set.prototype.clear = () => {
this.items = {}
}
// size方法
Set.prototype.size = () => {
return Object.keys(this.items).length
}
// values方法(获取集合中所有的值)
Set.prototype.values = () => {
return Object.keys(this.items)
}
}
// 测试类
// 1.创建set类对象
// let set = new Set()
// // 2.添加元素
// alert(set.add('aaa'))
// alert(set.add('aaa'))
// alert(set.add('bbb'))
// alert(set.add('ccc'))
// alert(set.add('ddd'))
// alert(set.values())
//
// // 3.删除元素
// alert(set.remove('ddd'))
// alert(set.remove('ddd'))
// alert(set.values())
//
// // 4.has方法
// alert(set.size())
// set.clear()
// alert(set.size())
集合间的操作:
- 并集: 对于给定的两个集合,返回一 个包含两个集合中所有元素的新集合 。
- 交集:对于给定的两个集合,返回一个包含两个集合中共有元素的新集合。
- 差集:对于给定的两个集合,返回个包含所有存在于第一个集合且不存在于第二个集合的元素的新集合。
- 子集:验证一个给定集合是否是另一集合的子集。
并集的实现
并集
- 并集其实对应就是数学中并集的概念
- 集合A和B的并集,表示为AUB,定义如下:
A U B = { x | x ∈ A V x ∈ B } - 意思是x(元素)存在于A中,或x存在于B中。
// 并集
Set.prototype.union = function(otherSet) {
// this: 集合对象A
// otherSet:集合对象B
// 1.创建新的集合
let unionSet = new Set()
// 2..将A集合中所有的元素添加到新集合中
let values = Object.keys(this.items)
console.log(this);
console.log(Object.keys(this.items));
for (let i = 0; i < values.length; i++){
unionSet.add(values[i])
}
// 3.取出B集合中的元素,判断是否需要加到新集合
values = Object.keys(otherSet.items)
console.log(values);
for (let i = 0; i < values.length; i++){
unionSet.add(values[i])
}
return unionSet
}
代码解析:
- 首先需要创建一个新的集合 ,代表两个集合的并集。
- 遍历集合1中所有的值并且添加到新集合中.
- 遍历集合2中所有的值并且添加到新集合中.
- 将最终的新集合返回.
交集的实现
交集
- 交集其实对应的就是数学中交集的概念
- 集合A和B的交集,表示为A∩B,定义如下:
A ∩ B= { x | x ∈ A ∧ x ∈ B } - 意思是x(元素)存在于A中,且x存在于B中。
// 交集
Set.prototype.intersection = function(otherSet){
// this: 集合对象A
// otherSet:集合对象B
// 1.创建新的集合
let intersectionSet = new Set()
// 2.从A中取出一个个元素,判断是否存在于集合B中,存在则放入新集合中
let values = Object.keys(this.items)
console.log(values);
for (let i = 0; i < values.length; i++) {
let item = values[i]
if (otherSet.items.hasOwnProperty(item)) {
intersectionSet.add(item)
}
}
return intersectionSet
}
代码解析:
- 创建一个新的集合.
- 遍历集合1中的所有元素,判断是否该元素在集合2中.
- 同时在集合2中,将该元素加入到新集合中
- 将最终的新集合返回.
差集实现
差集:
- 差集其实对应的就是数学中差集的概念
- 集合A和B的差集,表示为A-B,定义如下:
A - B = { x | x ∈ A ∧ x ∉ B } - 意思是x(元素)存在于A中,且x不存在于B中。
// 差集
Set.prototype.difference = function (otherSet) {
// this: 集合对象A
// otherSet:集合对象B
// 1.创建新的集合
let differenceSet = new Set()
let values = Object.keys(this.items)
console.log(values);
for (let i = 0; i < values.length; i++) {
let item = values[i]
if (!otherSet.items.hasOwnProperty(item)) {
differenceSet.add(item)
}
}
return differenceSet
}
代码解析:
- 创建个新的集合.
- 遍历集合1中所有的元素,判断是否在集合2中.
- 不存在于集合2中,将该元素添加到新集合中
- 将新集合返回
子集实现
子集:
- 子集其实对应的就是数学中子集的概念
- 集合A是B的子集(或集合B包含了A),表示为ACB,定义如下:
- 意思是集合A中的每一个x(元素),也需要存在于B中。
// 子集
Set.prototype.subset = function (otherSet) {
// this:集合A
// otherSet:集合B
// 遍历集合A中所有元素,如果发现,集合A中的元素在集合B中不存在,那么返回false
// 如果遍历完了真个集合,依然没有返回false,那么返回true即可
let values = Object.keys(this.items)
for (let i = 0; i < values.length; i++) {
let item = values[i]
if (!otherSet.items.hasOwnProperty(item)) return false
}
return true
}
代码解析:
- 判断集合1是否大于集合2,如果大于,那么肯定不是集合2的子集,
- 不大于的情况下:
➢判断集合1中的元索是否都在集合2中存在
➢存在,那么是集合2的子集,
➢有一个不存在那么不是集合2的子集
测试代码:
// 1.创建两个集合,并且添加元素
let setA = new Set()
setA.add('aaa')
setA.add('bbb')
setA.add('ccc')
// alert(setA.values())
let setB = new Set()
setB.add('aaa')
setB.add('ddd')
setB.add('ccc')
// alert(setB.values())
// 求两个集合的并集
let unionSet = setA.union(setB)
// alert(unionSet.values())
// 求两个集合的交集
let intersectionSet = setA.intersection(setB)
// alert(intersectionSet.values())
// 求两个集合的差集
let differenceSet = setA.difference(setB)
alert(differenceSet.values())