JS数据结构(7)——集合
1.什么是集合?
在ES6中提出了 set 这个数据结构,这也就是我们说的集合。
集合是由一组无序的、但不能重复的元素构成的。
我们可以把集合看成一个特殊的数组,特殊之处在于里面的元素,没有顺序,也不能重复。
没有顺序意味着不能通过下标值来进行访问,不能重复意味着相同的对象在集合中只会存在一份。
2.集合类的封装
代码思路:
- 在ES6中已经提出了 set 类,但是为了明确集合的内部实现机制,在这里我自己封装一个 Set 类。
- 在集合中,添加一个属性,用于保存之后添加到集合中的元素,我们使用Object来保存集合中的元素,因为Object的keys本身就是一个集合。
- 集合中常见的操作方法:
(1)add(value):向集合添加一个新的项
(2)remove(value):从集合移除一个值
(3)has(value):如果该值已经在集合中存在,返回true,否则返回false
(4)clear():移除集合中的所有项
(5)size():返回集合所包含元素的数量
(6)values():以数组形式返回集合中的所有值
还有很多关于集合的相关操作,可以在这些基本操作的基础上,自己尝试做一做。
代码实现:
function Set () {
// 属性
this.items = {};
// 方法
// has(value):如果该值已经在集合中存在,返回true,否则返回false
Set.prototype.has = function(value) {
return this.items.hasOwnProperty(value);
}
// add(value):向集合添加一个新的项
Set.prototype.add = function(value) {
// 判断当前集合中是否已经包含该元素
if(this.has(value))
return false;
// 将元素添加到集合中
this.items[value] = value;
return true;
}
// remove(value):从集合移除一个值
Set.prototype.remove = function(value) {
// 判断该集合中是否含有该元素
if(!this.has(value))
return false;
// 将元素从集合中删除
delete this.items[value];
return true;
}
// clear():移除集合中的所有项
Set.prototype.clear = function() {
this.items = {};
return true;
}
// size():返回集合所包含元素的数量
Set.prototype.size = function() {
return Object.keys(this.items).length;
}
// values():以数组形式返回集合中的所有值
Set.prototype.values = function() {
return Object.keys(this.items);
}
}
// 测试:
var set = new Set();
console.log(set.add(111)); //结果为:true
console.log(set.add(222)); //结果为:true
console.log(set.add(333)); //结果为:true
console.log(set.values()); //结果为:[ '111', '222', '333' ]
console.log(set.add(111)); //结果为:false
console.log(set.values()); //结果为:[ '111', '222', '333' ]
console.log(set.remove(222)); //结果为:true
console.log(set.values()); //结果为:[ '111', '333' ]
console.log(set.has(333)); //结果为:true
console.log(set.size()); //结果为:2
console.log(set.clear()); //结果为:true
console.log(set.values()); //结果为:[]
3.集合间的操作
代码思路:
- 并集:首先创建一个新的集合,代表两个集合的并集,遍历集合1和集合2的所有值,并添加到新集合中,将最终的新集合返回。
- 交集:首先创建一个新的集合,代表两个集合的交集,遍历集合1中的所有元素,判断是否在集合2中,若在,则将该元素加入到新集合中,将最终的新集合返回。
- 差集:首先创建一个新的集合,代表两个集合的差集,遍历集合1中的所有元素,判断是否在集合2中,若不在,则将元素添加到新集合中,将最终的新集合返回。
- 子集:判断集合1的长度是否大于集合2的长度,若大于,肯定不是集合2的子集。若不大于,判断集合1中的元素是否都在集合2中存在,都存在,则是集合2的子集,有一个不存在,则不是集合2的子集。
代码实现:
// 集合间的操作
// 并集
Set.prototype.union = function(otherSet) {
// 创建新的集合
var unionSet = new Set();
// 将集合1的所有元素添加到新集合中
var values1 = this.values();
for (var i = 0; i <values1.length; i++)
unionSet.add(values1[i]);
// 取出集合2的所有元素,判断是否要加入到新集合中
var values2 = otherSet.values();
for (var i = 0; i< values2.length; i++)
unionSet.add(values2[i]);
return unionSet;
}
// 交集
Set.prototype.intersection = function(otherSet) {
// 创建新的集合
var intersectionSet = new Set();
// 取出集合1中的所有元素
var values1 = this.values();
// 判断集合1中的元素是否在集合2中
for (var i = 0; i < values1.length; i++){
if(otherSet.has(values1[i]))
intersectionSet.add(values1[i]);
}
return intersectionSet;
}
// 差集
Set.prototype.difference = function(otherSet) {
// 创建新的集合
var differenceSet = new Set();
// 取出集合1中的所有元素
var values1 = this.values();
// 判断集合1中的元素是否在集合2中
for(var i = 0; i < values1.length; i++){
if(!otherSet.has(values1[i]))
differenceSet.add(values1[i]);
}
return differenceSet;
}
// 子集
Set.prototype.son = function(otherSet) {
// 判断集合1长度是否比集合2长度大
if(this.size() > otherSet.size())
return false;
// 取出集合1中的所有元素
var values1 = this.values();
// 判断集合1中的所有元素是否在集合2中
for (var i = 0; i < values1.length; i++){
if(!otherSet.has(values1[i]))
return false;
}
return true;
}
// 测试:
// 测试:集合间的操作
var set1 = new Set();
var set2 = new Set();
set1.add(111);
set1.add(222);
set1.add(333);
set2.add(222);
set2.add(333);
set2.add(444);
var unionSet = set1.union(set2);
console.log(unionSet.values()); // 结果为:[ '111', '222', '333', '444' ]
var intersectionSet = set1.intersection(set2);
console.log(intersectionSet.values()); // 结果为:[ '222', '333' ]
var differenceSet = set1.difference(set2);
console.log(differenceSet.values()); // 结果为:[ '111' ]
console.log(set1.son(set2)); // 结果为:false
var set3 = new Set();
set3.add(111);
console.log(set3.son(set1)); // 结果为:true