集合(set)是一种包含不同元素的数据结构。集合中的元素称为成员。
JavaScript中的集合与数学中的集合在很多地方上是相似的,例如,他们都拥有如下特性:
-
集合中的成员是无序的(无序性)
-
集合中不允许相同成员存在(互异性)
基本定义
与数学中的集合类似,他们都可以分为如下几类:
-
空集:不包含任何元素(成员)的集合称为空集
-
子集:如果一个集合中所有的成员都属于另外一个集合,则称那个集合为另一个集合的子集
-
相等:如果两个集合的成员完全相同,则称两个集合相等
-
全集:包含一切可能元素的集合
基本操作
这些基本操作也是在数学集合中出现的几个概念
-
并集:将两个集合中的成员进行合并,得到一个新集合
-
交集:两个集合中共同存在的成员组成一个新的集合
-
补集:属于一个集合而不属于另一个集合的成员组成的集合
实现一个集合
现在我们来实现一个JS集合,我们之前实现的很多种数据类型都是基于数组的,集合也不例外
function set() {
this.dataStore = [];
}
接着我们实现一些基本方法:
add() 方法
add()
方法用来向集合中加入元素(成员),因为集合的“互异性”,所以我们必须要检查一下集合中是否已经存在有要加入的元素:
function add(data) {
if (this.dataStore.indexOf(data) < 0) {
this.dataStore.push(data);
return true;
}
else {
return false;
}
}
remove()方法
remove()
方法和add()
方法的工作原理类似。首先检查待删元素是否在数组中,如果在,则使用数组的splice()
方法删除该元素并返回true
;否则,返回false
,表示集合中并不
存在这样一个元素。下面是remove()
方法的定义
function remove(data) {
var pos = this.dataStore.indexOf(data);
if (pos > -1) {
this.dataStore.splice(pos,1);
return true;
}
else {
return false;
}
}
show()方法
show()
方法用来展示该集合中的所有成员,非常简单
function show() {
return this.dataStore;
}
contains()方法
contains()
方法用来判断一个元素是否存在于这个集合之中
function contains(data) {
if (this.dataStore.indexOf(data) > -1) {
return true;
}
else {
return false;
}
}
union()方法
union()
方法执行并集操作,将两个集合合并成一个。该方法首先将第一个集合里的成员悉数加入一个临时集合,然后检查第二个集合中的成员,看它们是否也同时属于第一个集合。如果属于,则跳过该成员,否则就将该成员加入临时集合。
function union(set) {
var tempSet = new Set();
for (var i = 0; i < this.dataStore.length; ++i) {
tempSet.add(this.dataStore[i]);
}
for (var i = 0; i < set.dataStore.length; ++i) {
if (!tempSet.contains(set.dataStore[i])) {
tempSet.dataStore.push(set.dataStore[i]);
}
}
return tempSet;
}
subset()方法
subset()
方法是用来判断一个集合是否属于另一个集合的子集。
subset()
方法首先要确定该集合的长度是否小于待比较集合。如果该集合比待比较集合还要大,那么该集合肯定不会是待比较集合的一个子集。当该集合的长度小于待比较集合时,再判断该集合内的成员是否都属于待比较集合。如果有任意一个成员不属于待比较集合,则返回 false ,程序终止。如果一直比较完该集合的最后一个元素,所有元素都属于待比较集合,那么该集合就是待比较集合的一个子集,该方法返回 true 。
我们先要实现一个size()
方法来返回当前数组的长度:
function size() {
return this.dataStore.length;
}
接着我们实现subset()
方法:
function subset(set) {
if (this.size() > set.size()) {
return false;
}
else {
for each (var member in this.dataStore) {
if (!set.contains(member)) {
return false;
}
}
}
return true;
}
difference()
difference()
方法返回一个新集合,该集合包含的是那些属于第一个集合但不属于第二个集合的成员。此方法定义如下:
function difference(set) {
var tempSet = new Set();
for (var i = 0; i < this.dataStore.length; ++i) {
if (!set.contains(this.dataStore[i])) {
tempSet.add(this.dataStore[i]);
}
}
return tempSet;
}
完整代码
最后我们得到的完整的代码是这样的:
function Set() {
this.dataStore = [];
this.add = add;
this.remove = remove;
this.size = size;
this.union = union;
this.intersect = intersect;
this.subset = subset;
this.difference = difference;
this.show = show;
}
function add(data) {
if (this.dataStore.indexOf(data) < 0) {
this.dataStore.push(data);
return true;
}
else {
return false;
}
}
function remove(data) {
var pos = this.dataStore.indexOf(data);
if (pos > -1) {
this.dataStore.splice(pos,1);
return true;
}
else {
return false;
}
}
function show() {
return this.dataStore;
}
function contains(data) {
if (this.dataStore.indexOf(data) > -1) {
return true;
}
else {
return false;
}
}
function union(set) {
var tempSet = new Set();
for (var i = 0; i < this.dataStore.length; ++i) {
tempSet.add(this.dataStore[i]);
}
for (var i = 0; i < set.dataStore.length; ++i) {
if (!tempSet.contains(set.dataStore[i])) {
tempSet.dataStore.push(set.dataStore[i]);
}
}
return tempSet;
}
function size() {
return this.dataStore.length;
}
function subset(set) {
if (this.size() > set.size()) {
return false;
}
else {
for each (var member in this.dataStore) {
if (!set.contains(member)) {
return false;
}
}
}
return true;
}
function difference(set) {
var tempSet = new Set();
for (var i = 0; i < this.dataStore.length; ++i) {
if (!set.contains(this.dataStore[i])) {
tempSet.add(this.dataStore[i]);
}
}
return tempSet;
}