集合(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; }