求集合的并集,就是要将两个集合合并成一个,并除去重复的元素,我们实现思路就是将第一个集合成员放到一个临时集合中,判断第二个集合的成员是否也属于第一个集合,如果为真,代表为重复元素,我们直接跳过该成员,否则将该成员加入临时集合,最后返回该集合即可;
那么,问题来了,我们要如何判断一个成员是否存在于该集合中?因此,我们需要一个辅助方法 contains(),它的实现也非常简单,直接用 indexOf 判断即可
//判断元素是否属于该集合 function contains (data) { if( this.dataStore.indexOf(data) > -1 ){ return true; }else{ return false; } }
现在,我们可以定义 union 方法了
//求集合的并集 function union ( set ) { var tempSet = new MySet(); for( var i = 0 ; i < this.dataStore.length ; i++ ){ tempSet.add(this.dataStore[i]); } for( var i = 0 ; i< set.dataStore.length ; i++ ){ if( !tempSet.contains(set.dataStore[i])){ tempSet.dataStore.push(set.dataStore[i]); } } return tempSet; }
这样,我们就可以就集合的并集了,
var fruits1 = new MySet(); fruits1.add('Apple'); fruits1.add('Banana'); fruits1.add('Pear'); var fruits2 = new MySet(); fruits2.add('Grape'); fruits2.add('Banana'); fruits2.add('Pear'); fruits2.add('Orange'); var union = fruits1.union( fruits2 ); union.show(); // ["Apple", "Banana", "Pear", "Grape", "Orange"]
成功了!我们可以来看看求集合的交集了。
intersect:求集合的交集
有了上面求并集的思路,那么交集的定义来说也相对简单,思路就是发现第一个集合的成员也属于第二个集合时,就将该成员加入到新的集合,最后返回新的集合即可;
//求集合的交集 function intersect (set) { var tempSet = new MySet(); for(var i = 0 ; i < this.dataStore.length ; i++ ){ if( set.contains(this.dataStore[i])){ tempSet.add(this.dataStore[i]); } } return tempSet; }
我们还是利用上面的两个集合接着求其交集:
var intersect = fruits1.intersect( fruits2 ); intersect.show(); // ["Banana", "Pear"]
下一个定义的操作是 subset ;
subset:判断集合是否是另一集合的子集
该方法首先要确定 该集合的长度是否小于待比较的集合。如果该集合比待比较集合还要大,那么肯定不是待比较集合的一个子集。只要当,待比较集合比较大时,才去判断集合类的成员是否都属于待比较集合,如果有一个不是,直接返回 false , 只有当所有元素都属于待比较集合的时候,我们才能说该集合是待比较集合的一个子集,该方法才会返回 true , 为了方便查看,我加入了console打印;
//子集判断 function subset (set) { if( this.size() > set.size() ){ console.log('not a subset'); return false; }else{ for ( var i = 0 ; i < this.dataStore.length ; i++ ){ if( !set.contains(this.dataStore[i])){ console.log('not a subset'); return false; } } } console.log(' a subset'); return true; }
我们看到上面用到了 size 方法,它的定义如下:
//返回集合长度 function size () { return this.dataStore.length; }
我们保留上面的 fruits1 和 fruits2 , 新建一个 fruits3 来演示 subset 方法
var fruits3 = new MySet(); fruits3.add('Apple'); fruits3.add('Banana'); fruits3.add('Pear'); fruits3.add('Grape'); fruits3.add('Orange'); //子集判断 fruits1.subset( fruits2 ); // not a subset fruits2.subset( fruits2 ); // a subset fruits1.subset( fruits3 ); // a subset
看起来一切都很顺利,我们只剩最后一个 difference 方法,该方法返回一个新集合,该集合是由属于第一个集合而不属于第二个集合的成员组成的。
difference:补集
有了交集的思路,补集的实现就显得很自然了。
//补集 function difference (set) { var tempSet = new MySet(); for( var i = 0 ; i < this.dataStore.length ; i ++ ){ if( !set.contains(this.dataStore[i])){ tempSet.dataStore.push( this.dataStore[i] ); } } return tempSet; }
我们测试一下:
fruits1.difference(fruits2).show(); // ['Apple'] fruits1.difference(fruits3).show(); // [] fruits2.difference(fruits1).show(); // ["Grape", "Orange"]
ok,到现在,我们完成了一个完整的 set 集合,是不是很棒!
本篇介绍的集合和 ES6 的集合略微有点差别,ES6 提供的 Set 数据结构,有很多现成的方法可以直接调用,很是方法,不是很了解的小伙伴可以参考我之前的一篇博文,关于ES6中Symbol 、Set 和 Map 一文,相信会有不错的收获~