集合(set
)是一種包含不一樣元素的數據結構. 集合中的元素稱爲成員. 集合的兩個最重要的特性是: 首先, 集合中的成員是無序的; 其次, 集合中不容許相同成員存在. 集合在計算機科學中扮演了很是重要的角色, 然而在不少編程語言中, 並不把集合當成一種數據類型. 當你想要建立一個數據結構, 用來保存一些獨一無二的元素時, 好比一段文本中用到的單詞, 集合就變得很是有用.
在ES6
中已加入集合Set
集合是由一組無序但彼此之間又有必定相關性的成員構成的, 每一個成員在集合中只能出現一次.編程
下面是一些使用集合必須瞭解的定義.數組
對集合的基本操做有下面幾種:數據結構
Set
類的實現Set
類的實現基於數組, 數組用來存儲數據.編程語言
window.log = console.log.bind(console) class Set { constructor() { this._dataStore = []; } add(data) { if(!this._dataStore.includes(data)) { this._dataStore.push(data); return true; }; return false; } remove(data) { const pos = this._dataStore.indexOf(data); if(pos > -1) { this._dataStore.splice(pos, 1); return true; }; return false; } show() { return this._dataStore; } };
add()
方法: 由於集合中不能包含相同的元素, 因此, 使用add()
方法將數據存儲到數組前, 先要確保數組中不存在該數據. 咱們使用indexof()
檢查新加入的元素在數組是否存在. 若是找到, 該方法返回該元素在數組中的位置; 若是沒找到, 該方法返回-1
. 若是數組中還未包含該元素, add()
方法將新加入的元素保存在數組中並返回true
; 反之返回false
. 將add()
方法的返回值定義爲布爾類型, 能夠明確告訴咱們是否將一個元素成功加入到了集合中. 這裏使用ES6
中的includes()
也是能夠的.測試
remove()
方法和add()
方法的工做原理相似. 首先檢查待刪除元素是否在數組中, 如何在, 則使用數組的splice()
方法刪除該元素並返回true
; 反之返回false
, 表示集合中不存在這樣的一個元素.this
show()
顯示集合中的成員.
測試程序:code
const s = new Set(); s.add('a'); s.add('b'); s.add('c'); s.add('d'); s.add('e'); s.add('f'); log(s.show()); if(s.add('f')) { log('f: 添加成功') } else { log('已存在f, 添加失敗') }
輸出:rem
(6) ["a", "b", "c", "d", "e", "f"] 已存在f, 添加失敗
定義union()
、subset()
和difference()
方法會更有意思. union()
方法執行並集操做, 將兩個集合合併成一個. 該方法首先將第一個集合裏的成員悉數加入一個臨時集合, 而後檢查第二個集合中的成員, 看它們是否也同時屬於第一個集合. 若是屬於, 則跳過該成員, 不然就將該成員加入臨時集合.io
在定義union()
方法前, 先定一個輔助方法contains()
, 該方法檢查一個成員是否屬於該集合.console
contains(data) { return this._dataStore.includes(data); } // 並集 union(set) { const tempSet = new Set(); this._dataStore.forEach(i => { tempSet.add(i); }); set._dataStore.forEach(i => { if(!tempSet.contains(i)) { tempSet._dataStore.push(i) } }); return tempSet; }
執行程序:
const s = new Set(); s.add('a'); s.add('b'); s.add('c'); s.add('d'); s.add('e'); s.add('f'); log(s.show()); const s1 = new Set(); s1.add('a'); s1.add('f'); s1.add('g'); let res = new Set(); res = s.union(s1); log(res.show()); //輸出: // (6) ["a", "b", "c", "d", "e", "f"] // (7) ["a", "b", "c", "d", "e", "f", "g"]
使用intersect()
方法求兩個集合的交集. 該方法定義起來相對簡單. 每當發現第一個集合的成員也屬於第二個集合時, 便將該成員加入一個心機和, 這個心機和即爲方法的返回值.
// 交集 intersect(set) { const tempSet = new Set(); this._dataStore.forEach(i => { if(set.contains(i)) { tempSet.add(i) }; }); return tempSet; }
下一個要定義的操做是subset()
判斷子集. subset()
方法首先要肯定該集合的長度是否小於帶比較集合.
若是該集合比帶比較集合還要大, 那麼該集合確定不會是待比較集合的一個子集.
當集合的長度小於待比較集合時, 再判斷該集合內的成員是否都屬於待比較集合. 若是有任意一個成員不屬於待比較集合, 則返回false
, 程序終止. 若是一直比較完該集合的最後一個元素, 全部元素都屬於待比較集合, 那麼該集合就是待比較集合的一個子集, 該方法返回true
.
在判斷每一個元素是否屬於待比較集合前, 該方法先使用size()
方法對比兩個集合的大小.
size() { return this._dataStore.length; } subSet(set) { if(this.size() > set.size()) { return false; }; for(let i = 0; i < this._dataStore.length; i++) { if(!set.contains(this._dataStore[i])) { return false; }; }; return true; }
最後一個操做是difference()
補集, 該方法返回一個新集合, 該集合包含的是那些屬於第一個集合但不屬於第二個集合的成員.
difference(set) { const tempSet = new Set(); this._dataStore.forEach(i => { if(!set.contains(i)) { tempSet.add(i); }; }); return tempSet; }