在數據結構之前,集合首先是個非常重要的數學概念,離散數學的第一課應該都是講集合吧。。。
在數據結構中,集合是由一組無序且唯一的項組成的。這裏對這種數據結構進行了封裝,使用對象來存儲項(鍵和值都爲該項自身),提供了添加項、刪除項等一系列基本的集合操作方法。並在構造器對象上定義了求兩集合並集、交集、差集、笛卡爾積、環積的方法,以及判斷是否爲子集、真子集、同一集合的方法。 關於構造器對象上定義的這些方法,大家可以將它添加至原型對象中並進行相應修改,使得可以自動將調用對象作爲方法的第一個參數。 這裏還支持鏈式調用。 各方法功能見代碼註釋:
//set
function Set(){
//私有變量
var items = {},
size = 0;
//向集合中添加元素 Object(Set)
this.add = function(value){
if(!this.has(value)){
items[value] = value;
size++;
return this;
}
throw 'Set.add() false';
return false;
};
//從集合中移除元素 Object(Set)
this.remove = function(value){
if(this.has(value)){
delete items[value];
size--;
return this;
}
throw 'Set.remove() false';
return false;
};
//集合中是否存在該元素 Boolean
this.has = function(value){
return items.hasOwnProperty(value);
};
//清空集合 true
this.clear = function(){
items = {};
size = 0;
return true;
};
//集合大小 Number
this.size = function(){
return size;
};
//集合中的元素列表 Object(Array)
this.values = function(){
return Object.keys(items);
};
}
//在構造器對象上定義了一系列集合運算方法 可以直接調用
//求交集 Object(Set)
Set.intersection = function(set1, set2){
var res = new Set(),
temp = set1.values();
for(var i in temp){
if(set2.has(temp[i]))
res.add(temp[i]);
}
return res;
}
//求並集 Object(Set)
Set.union = function(set1, set2){
var res = new Set(),
temp = set1.values(),
temp2 = set2.values();
for(var i in temp)
res.add(temp[i]);
for(var j in temp2)
res.add(temp2[j]);
return res;
}
//求差集set1-set2 Object(Set)
Set.difference = function(set1, set2){
var res = new Set(),
temp = set1.values();
for(var i in temp)
if(!set2.has(temp[i]))
res.add[temp[i]];
return res;
}
//求笛卡兒積 這裏用數組表示序偶 Object(Set)
Set.cartesianProduct = function(set1,set2){
var res = new Set(),
temp1 = set1.values(),
temp2 = set2.values();
for(var i = 0; i < temp1.length;i++)
for(var j = 0;j < temp2.length;j++)
res.add([temp1[i],temp2[j]]);
return res;
}
//求對稱差 Object(Set)
Set.symmetricDifference = function(set1, set2){
return Set.union(Set.difference(set1, set2),Set.difference(set2,set1));
}
//set1是否是set2的子集 Boolean
Set.isSubset = function(set1, set2){ // if set1 is set2's subset, return true
var temp = set1.values();
for(var i in temp)
if(!set2.has(temp[i]))
return false;
return true;
}
//set1是否是set2的真子集 Boolean
Set.isProperSubset = function(set1, set2){ // if set1 is set2's proper subset, return true
if(set1.size() >= set2.size())
return false;
return Set.isSubset(set1, set2);
//another
//return Set.isSubset(set1, set2) && !Set.equality(set1, set2);
}
//兩集合是否相等
Set.equality = function(set1, set2){
return Set.isSubset(set1, set2) && Set.isSubset(set2, set1);
}
其實在寫面向對象系列後,有點小強迫症,特別想把方法都寫進原型對象裏。但是這裏因爲要通過閉包實現私有變量,必須將方法放進構造函數中。 如果非要把方法寫在原型對象裏的話,構造函數裏也得定義對私有變量的訪問接口方法,那感覺就真有點畫蛇添足了。