定义
set是不允许重复元素的集合类型,set体系最常用的是HashSet ,TreeSet, LinkedHashSet。相同的元素是放不进去set的。
HasHSet是使用HashMap实现的,只是将value固定为一个静态对象,使用key保证集合的唯一性,但是不保证顺序性。
LinkedHashMap是继承自HashSet,具有HashSet的优点,内部使用链表维护了插入顺序。
创建集合
let items = {};
我们使用对象而不是数组来表示集合(items)的原因有两个:
- 第一个是因为在使用数组时,大部分方法的时间复杂度是O(n)。即我们需要迭代整个数组直到找到要找的那个元素,在最坏的情况下需要迭代数组的所有位置。如果数组有更多元素的话,所需的时间会更长。另外,数组是元素的一个有序集合。为了保证元素排列有序,它会占用更多的内存空间。
- 另一个就是因为Javascript的对象不允许一个键指向两个不同属性,也保证了集合里的元素都是唯一的。
函数说明及注释
//如果值在集合中, 返回true, 否则返回false。
this.has = function (value) {
// return value in items;
return items.hasOwnProperty(value);
};
//向集合添加一个新的项。
this.add = function (value) {
if (!this.has(value)) {
items[value] = value; //检查该元素是否在集合中,进行添加
return true;
}
return false;
};
// 从集合移除一个值
this.remove = function (value) {
if (this.has(value)) {
delete items[value]; //存在该元素,进行移除
return true;
}
return false;
};
//移除集合中的所有项
this.clear = function () {
items = {}; // 直接制空
};
//返回集合所包含元素的数量。 与数组的length属性类似。
this.size = function () {
return Object.keys(items).length; //返回长度
};
//在所有浏览器中适用的size改进函数
this.sizeLegacy = function () {
let count = 0;
for (let key in items) { //遍历items对象的所有属性
if (items.hasOwnProperty(key)) //检查它们是否是对象自身的属性,避免重复计数
++count; //递增
}
return count;
};
//返回一个包含集合中所有值的数组
//Chrome Firefox IE10+
this.values = function () {
let values = [];
for (let i = 0, keys = Object.keys(items); i < keys.length; i++) {
values.push(items[keys[i]]); //使用push方法将值进行传递
}
return values; //返回数组
};
//all browers
this.valuesLegacy = function () {
let values = [];
for (let key in items) { //遍历items对象的所有属性
if (items.hasOwnProperty(key)) { //添加一个数组
values.push(items[key]); //push进去
}
}
return values;
};
代码测试
let set = new Set();
set.add(1);
console.log(set.values()); //输出["1"]
console.log(set.has(1)); //输出true
console.log(set.size()); //输出1
set.add(2);
console.log(set.values()); //输出["1", "2"]
console.log(set.has(2)); //true
console.log(set.size()); //2
set.remove(1);
console.log(set.values()); //输出["2"]
set.remove(2);
console.log(set.values()); //输出[]
并集操作
- 对于给定的两个集合,返回一个包含两个集合中所有元素的新集合
//进行并集操作
this.union = function (otherSet) {
let unionSet = new Set(); // 创建一个并集数组
let values = this.values(); //遍历并全部添加到代表并集的集合中
for (let i = 0; i < values.length; i++) {
unionSet.add(values[i]);
}
values = otherSet.values(); //遍历并全部添加到代表并集的集合中
for (let i = 0; i < values.length; i++) {
unionSet.add(values[i]);
}
return unionSet;
}
代码测试
let setA = new Set();
setA.add(1);
setA.add(2);
setA.add(3);
console.log(setA.values());
let setB = new Set();
setB.add(3);
setB.add(4);
setB.add(5);
setB.add(6);
console.log(setB.values());
let unionAB = setA.union(setB);
console.log(unionAB.values()); //1,2,3,4,5,6
交集操作
- 对于给定的两个集合,返回一个包含两个集合中共有元素的新集合。
//进行交集操作
this.intersection = function (otherSet) {
let intersectionSet = new Set(); //创建一个新的Set实例
let values = this.values();
for (let i = 0; i < values.length; i++) { //遍历当前Set实例所有的值
if (otherSet.has(values[i])) { //验证它们是否也存在于otherSet实例
intersectionSet.add(values[i]); //添加到创建的intersectionSet变量中
}
}
return intersectionSet;
}
代码测试
let setA = new Set();
setA.add(1);
setA.add(2);
setA.add(3);
console.log(setA.values());
let setB = new Set();
setB.add(2);
setB.add(3);
setB.add(4);
console.log(setB.values());
let intersectionAB = setA.intersection(setB);
console.log(intersectionAB.values()); //2,3
差集操作
- 对于给定的两个集合,返回一个包含所有存在于第一个集合且不存在于第二个集合的元素的新集合
//进行差集操作
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;
};
代码测试
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 differenceAB = setA.difference(setB);
console.log(differenceAB.values()); //1
判断子集
- 验证一个给定集合是否是另一个集合的子集。
//判断是否是子集
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; //存在子集
}
};
代码测试
let setA = new Set(); //1,2
setA.add(1);
setA.add(2);
let setB = new Set(); //1,2,3
setB.add(1);
setB.add(2);
setB.add(3);
let setC = new Set(); //2,3,4
setC.add(2);
setC.add(3);
setC.add(4);
console.log(setA.subset(setB)); //true B是A的子集
console.log(setA.subset(setC)); //false C不是A的子集