TypeScript方式实现源码
// 特性: // 1. 集合是由一组无序且唯一(即不能重复)的项组成的。这个数据结构使用了与有限集合相同的数学概念,但应用在计算机科学的数据结构中。 // 2. 也可以把集合想象成一个既没有重复元素,也没有顺序概念的数组 // 3. 在数学中,集合也有并集、交集、差集等基本操作。在这一章中我们也会介绍这些操作 // 集合操作 // 并集:对于给定的两个集合,返回一个包含两个集合中所有元素的新集合 // 并集的数学概念,集合A和B的并集,表示为A∪B,定义如下: // A∪B = { x | x ∈ A∨x ∈ B } // 意思是x(元素)存在于A中,或x存在于B中。下图展示了并集操作: // 并集.png // 交集:对于给定的两个集合,返回一个包含两个集合中共有元素的新集合 // 交集的数学概念,集合A和B的交集,表示为A∩B,定义如下: // A∩B = { x | x ∈ A∧x ∈ B } // 意思是x(元素)存在于A中,且x存在于B中。下图展示了交集操作: // 交集.png // 差集:对于给定的两个集合,返回一个包含所有存在与第一个集合且不存在与第二个集合的元素的新集合 // 差集的数学概念,集合A和B的差集,表示为AB,定义如下: // AB = { x | x ∈ A ∧ x B } // 意思是x(元素)存在于A中,且x不存在于B中。下图展示了集合A和B的差集操作: // 差集.png // 子集:验证一个给定集合是否是另一个集合的子集 // 最后一个集合操作是子集。子集的数学概念,集合A是B的子集(或集合B包含 // 了A) ,表示为A⊆B,定义如下: // ∀x { x ∈ A → x ∈ B } // 意思是集合A中的每一个x(元素) ,也需要存在于B中。下图展示了集合A是集合B的子集: // 子集.png
1 class Set { 2 private items: Object = {}; 3 /** 4 * 向集合添加一个新的项 5 * @param value 6 */ 7 public add(value) { 8 if (!this.has(value)) { 9 this.items[value] = value; 10 return true; 11 } 12 } 13 /** 14 * 从集合移除一个值 15 * @param value 16 */ 17 public remove(value) { 18 if (this.has(value)) { 19 delete this.items[value]; 20 return true; 21 } 22 return false; 23 } 24 /** 25 * 如果值在集合中,返回true,否则返回false 26 * @param value 27 */ 28 public has(value) { 29 return this.items.hasOwnProperty(value); 30 } 31 /** 32 * 移除集合中的所有项 33 */ 34 public clear() { 35 this.items = {}; 36 } 37 /** 38 * 返回集合所包含元素的数量。与数组的length属性类似 39 */ 40 public size() { 41 var count = 0; 42 for (var prop in this.items) { //{5} 43 if (this.items.hasOwnProperty(prop)) //{6} 44 ++count; //{7} 45 } 46 return count; 47 } 48 /** 49 * 返回一个包含集合中所有值的数组 50 */ 51 public values() { 52 var keys = []; 53 for (var key in this.items) { //{7} 54 keys.push(key); //{8} 55 } 56 return keys; 57 } 58 public union(otherSet: Set): Set { 59 let unionSet = new Set(); 60 61 let values = this.values(); 62 for (let i = 0; i < values.length; i++) { 63 unionSet.add(values[i]); 64 } 65 66 values = otherSet.values(); 67 for (let i = 0; i < values.length; i++) { 68 unionSet.add(values[i]); 69 } 70 return unionSet; 71 } 72 public intersection(otherSet: Set) { 73 let intersectionSet = new Set(); 74 let values = this.values(); 75 for (let i = 0; i < values.length; i++) { 76 if (otherSet.has(values[i])) { 77 intersectionSet.add(values[i]); 78 } 79 } 80 return intersectionSet; 81 } 82 public difference(otherSet: Set) { 83 let differenceSet = new Set(); 84 let values = this.values(); 85 for (let i = 0; i < values.length; i++) { 86 if (!otherSet.has(values[i])) { 87 differenceSet.add(values[i]); 88 } 89 } 90 return differenceSet; 91 } 92 public subset(otherSet: Set) { 93 if (this.size() > otherSet.size()) { 94 return false; 95 } else { 96 let values = this.values(); 97 for (let i = 0; i < values.length; i++) { 98 if (!otherSet.has(values[i])) { 99 return false; 100 } 101 } 102 return true; 103 } 104 } 105 106 }
1 // 使用 Set 类 2 let set = new Set(); 3 4 set.add(1); 5 console.log(set.values()); //输出["1"] 6 console.log(set.has(1)); //输出true 7 console.log(set.size()); //输出1 8 9 set.add(2); 10 console.log(set.values()); //输出["1", "2"] 11 console.log(set.has(2)); //true 12 console.log(set.size()); //2 13 14 set.remove(1); 15 console.log(set.values()); //输出["2"] 16 17 set.remove(2); 18 console.log(set.values()); //输出[] 19 20 // 测试一下并集的代码: 21 var setA = new Set(); 22 setA.add(1); 23 setA.add(2); 24 setA.add(3); 25 26 var setB = new Set(); 27 setB.add(3); 28 setB.add(4); 29 setB.add(5); 30 setB.add(6); 31 32 var unionAB = setA.union(setB); 33 console.log(unionAB.values()); 34 35 // 测试一下交集的代码 36 var setA = new Set(); 37 setA.add(1); 38 setA.add(2); 39 setA.add(3); 40 41 var setB = new Set(); 42 setB.add(2); 43 setB.add(3); 44 setB.add(4); 45 46 var intersectionAB = setA.intersection(setB); 47 console.log(intersectionAB.values()); 48 //输出为["2", "3"],因为2和3同时存在于两个集合中 49 50 // 测试一下差集的代码 51 var setA = new Set(); 52 setA.add(1); 53 setA.add(2); 54 setA.add(3); 55 56 var setB = new Set(); 57 setB.add(2); 58 setB.add(3); 59 setB.add(4); 60 61 var differenceAB = setA.difference(setB); 62 console.log(differenceAB.values()); 63 //输出为["1"],因为1是唯一一个仅存在于setA的元素。 64 65 // 测试一下子集的代码 66 var setA = new Set(); 67 setA.add(1); 68 setA.add(2); 69 70 var setB = new Set(); 71 setB.add(1); 72 setB.add(2); 73 setB.add(3); 74 75 var setC = new Set(); 76 setC.add(2); 77 setC.add(3); 78 setC.add(4); 79 80 console.log(setA.subset(setB)); 81 console.log(setA.subset(setC)); 82 // 我们有三个集合:setA是setB的子集 (因此输出为true) , 然而setA不是setC的子集 (setC 83 // 只包含了setA中的2,而不包含1) ,因此输出为false
总结:我们将从头实现一个与ECMAScript 6中定义的类似的Set类。我们还介绍了在其他编程语言的集合数据结构的实现中不常见的一些方法,比如并集、交集、差集和子集。因此,相比于其他编程语言目前的Set实现,我们实现了一个非常完备的Set类
JavaScript方式实现源码
1 var Set = (function () { 2 function Set() { 3 this.items = {}; 4 } 5 /** 6 * 向集合添加一个新的项 7 * @param value 8 */ 9 Set.prototype.add = function (value) { 10 if (!this.has(value)) { 11 this.items[value] = value; 12 return true; 13 } 14 }; 15 /** 16 * 从集合移除一个值 17 * @param value 18 */ 19 Set.prototype.remove = function (value) { 20 if (this.has(value)) { 21 delete this.items[value]; 22 return true; 23 } 24 return false; 25 }; 26 /** 27 * 如果值在集合中,返回true,否则返回false 28 * @param value 29 */ 30 Set.prototype.has = function (value) { 31 return this.items.hasOwnProperty(value); 32 }; 33 /** 34 * 移除集合中的所有项 35 */ 36 Set.prototype.clear = function () { 37 this.items = {}; 38 }; 39 /** 40 * 返回集合所包含元素的数量。与数组的length属性类似 41 */ 42 Set.prototype.size = function () { 43 var count = 0; 44 for (var prop in this.items) { 45 if (this.items.hasOwnProperty(prop)) 46 ++count; //{7} 47 } 48 return count; 49 }; 50 /** 51 * 返回一个包含集合中所有值的数组 52 */ 53 Set.prototype.values = function () { 54 var keys = []; 55 for (var key in this.items) { 56 keys.push(key); //{8} 57 } 58 return keys; 59 }; 60 Set.prototype.union = function (otherSet) { 61 var unionSet = new Set(); 62 var values = this.values(); 63 for (var i_1 = 0; i_1 < values.length; i_1++) { 64 unionSet.add(values[i_1]); 65 } 66 values = otherSet.values(); 67 for (var i_2 = 0; i_2 < values.length; i_2++) { 68 unionSet.add(values[i_2]); 69 } 70 return unionSet; 71 }; 72 Set.prototype.intersection = function (otherSet) { 73 var intersectionSet = new Set(); 74 var values = this.values(); 75 for (var i_3 = 0; i_3 < values.length; i_3++) { 76 if (otherSet.has(values[i_3])) { 77 intersectionSet.add(values[i_3]); 78 } 79 } 80 return intersectionSet; 81 }; 82 Set.prototype.difference = function (otherSet) { 83 var differenceSet = new Set(); 84 var values = this.values(); 85 for (var i_4 = 0; i_4 < values.length; i_4++) { 86 if (!otherSet.has(values[i_4])) { 87 differenceSet.add(values[i_4]); 88 } 89 } 90 return differenceSet; 91 }; 92 Set.prototype.subset = function (otherSet) { 93 if (this.size() > otherSet.size()) { 94 return false; 95 } 96 else { 97 var values = this.values(); 98 for (var i_5 = 0; i_5 < values.length; i_5++) { 99 if (!otherSet.has(values[i_5])) { 100 return false; 101 } 102 } 103 return true; 104 } 105 }; 106 return Set; 107 }());