集合是由一組無序且唯一的項組成,ECMAScript2015(ES6)包括了Set類的實現,下面用ES5模擬實現ES6中的Set類
1.創建集合
我們用對象來實現Set類,當然也可以用數組,js對象一個鍵不能指向兩個值,這保證了集合元素的唯一性。先初始化Set類
function Set() { var items = {}; }
1.1 has方法
this.has = function(value){ return value in items; }
用js的in操作符驗證給定值是否是items對象的屬性,這個方法還有更好的一個實現,那就是用js對象都有的hasOwnProperty方法
this.has = function(value){ return items.hasOwnProperty(value); }
1.2 add方法
this.add = function(value){ if (!this.has(value)) { items[value] = value; return true; } return false; }
注:添加一個值時,把它同時作為鍵和值保存,這樣有利於查找該值
1.2 remove和clear方法
this.remove = function(value){ if (this.has(value)) { delete value; return true; } return false; }, this.clear = function(){ items={}; }
1.3 size方法
size方法的實現可以使用一個length屬性,每當調用add和remove方法時動態更新其值;
也可以使用js的Object類實現
this.size = function(){ return Object.keys(items).length; }
最后一種方法是,手動統計items對象的屬性數量
this.size = function(){ var count = 0; for(var prop in items){ if (items.hasOwnProperty(prop)) { ++count; } } return count; }
1.4 values方法
values方法提取items對象所有屬性,以數組形式返回
this.values= function(){ var values = []; for(var value in items){ if (items.hasOwnProperty(value)) { values.push(value); } } return values; }
2.集合操作
2.1 並集
創建一個新集合代表兩個集合的並集,分別變量兩個集合的所有值,將他們添加到代表並集的集合中,最后返回並集。
this.union = function(otherSet){ var unionSet = new Set(); var values = this.values(); for (var i = 0; i < values.length; i++) { unionSet.add(values[i]); } values = otherSet.values(); for (var i = 0; i < values.length; i++) { unionSet.add(values[i]); } return unionSet; }
2.2 交集
創建一個新集合代表兩個集合的交集,遍歷一個集合的所有值,將另一個集合中同樣也含有的值,添加到代表交集的集合中,最后返回交集。
this.intersection = function(otherSet){ var intersection = new Set(); var values = this.values(); for (var i = 0; i < values.length; i++) { if (otherSet.has(values[i])) { intersection.add(values[i]); } } return intersection; }
2.3 差集
差集實現和交集類似,只不過是遍歷一個集合的所有值,將另一個集合中不在這個集合中的值,添加到代表差集的集合中,最后返回差集。
this.difference = function(otherSet){ var difference = new Set(); var values = this.values(); for (var i = 0; i < values.length; i++) { if (!otherSet.has(values[i])) { difference.add(values[i]); } } return difference; }
2.4 子集
判斷調用subset方法的集合是不是otherSet的子集
this.subset = function(otherSet){ var values = this.values(); if (this.size() > otherSet.size()) { return false; } else{ for (var i = 0; i < values.length; i++) { if (!otherSet.has(values[i])) { return false; } } return true; } }
下面給出完整實現的Set類
function Set() { var items = {}; // this.has = function(value){ // return value in items; // } this.has = function(value){ 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 value; return true; } return false; }, this.clear = function(){ items={}; }, this.size = function(){ var count = 0; for(var prop in items){ if (items.hasOwnProperty(prop)) { ++count; } } return count; }, this.values= function(){ var values = []; for(var value in items){ if (items.hasOwnProperty(value)) { values.push(value); } } return values; }, this.union = function(otherSet){ var unionSet = new Set(); var values = this.values(); for (var i = 0; i < values.length; i++) { unionSet.add(values[i]); } values = otherSet.values(); for (var i = 0; i < values.length; i++) { unionSet.add(values[i]); } return unionSet; }, this.intersection = function(otherSet){ var intersection = new Set(); var values = this.values(); for (var i = 0; i < values.length; i++) { if (otherSet.has(values[i])) { intersection.add(values[i]); } } return intersection; }, this.difference = function(otherSet){ var difference = new Set(); var values = this.values(); for (var i = 0; i < values.length; i++) { if (!otherSet.has(values[i])) { difference.add(values[i]); } } return difference; }, this.subset = function(otherSet){ var values = this.values(); if (this.size() > otherSet.size()) { return false; } else{ for (var i = 0; i < values.length; i++) { if (!otherSet.has(values[i])) { return false; } } return true; } } }
