在集合代数中除了对集合基本性质和规律的描述外,还包含了对各种集合运算和集合关系的说明。集合的运算包括并集,交集,差集还有对称差集。集合的关系包括相等和真包含。这篇文章我们就来实现这些功能。
首先我们添加集合真包含的判断功能。根据集合代数中的描述,如果集合 A 真包含了集合 B,那么就可以说集合 A 是集合 B 的一个超集。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| func (set *HashSet) IsSuperset(other *HashSet) bool { if other == nil { return false } setLen := set.Len() otherLen := other.Len() if setLen == 0 || setLen == otherLen { return false } if setLen > 0 && otherLen == 0 { return true } for _, v := range other.Elements() { if !set.Contains(v) { return false } } return true }
|
集合的运算包括并集、交集、差集和对称差集。
并集运算是指把两个集合中的所有元素都合并起来并组合成一个集合。
交集运算是指找到两个集合中共有的元素并把它们组成一个集合。
集合 A 对集合 B 进行差集运算的含义是找到只存在于集合 A 中但不存在于集合 B 中的元素并把它们组成一个集合。
对称差集运算与差集运算类似但有所区别。对称差集运算是指找到只存在于集合 A 中但不存在于集合 B 中的元素,再找到只存在于集合 B 中但不存在于集合 A 中的元素,最后把它们合并起来并组成一个集合。
实现并集运算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| func (set *HashSet) Union(other *HashSet) *HashSet { if set == nil || other == nil { return nil } unionedSet := NewHashSet() for _, v := range set.Elements() { unionedSet.Add(v) } if other.Len() == 0 { return unionedSet } for _, v := range other.Elements() { unionedSet.Add(v) } return unionedSet }
|
实现交集运算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| func (set *HashSet) Intersect(other *HashSet) *HashSet { if set == nil || other == nil { return nil } intersectedSet := NewHashSet() if other.Len() == 0 { return intersectedSet } if set.Len() < other.Len() { for _, v := range set.Elements() { if other.Contains(v) { intersectedSet.Add(v) } } } else { for _, v := range other.Elements() { if set.Contains(v) { intersectedSet.Add(v) } } } return intersectedSet }
|
差集
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| func (set *HashSet) Difference(other *HashSet) *HashSet { if set == nil || other == nil { return nil } differencedSet := NewHashSet() if other.Len() == 0 { for _, v := range set.Elements() { differencedSet.Add(v) } return differencedSet } for _, v := range set.Elements() { if !other.Contains(v) { differencedSet.Add(v) } } return differencedSet }
|
对称差集
1 2 3 4 5 6 7 8 9 10 11 12
| func (set *HashSet) SymmetricDifference(other *HashSet) *HashSet { if set == nil || other == nil { return nil } diffA := set.Difference(other) if other.Len() == 0 { return diffA } diffB := other.Difference(set) return diffA.Union(diffB) }
|
4.进一步重构
目前所实现的 HashSet 类型提供了一些必要的集合操作功能,但是不同应用场景下可能会需要使用功能更加丰富的集合类型。当有多个集合类型的时候,应该在它们之上抽取出一个接口类型以标识它们共有的行为方式。依据 HashSet 类型的声明,可以如下声明 Set 接口类型:
1 2 3 4 5 6 7 8 9 10
| type Set interface { Add(e interface{}) bool Remove(e interface{}) Clear() Contains(e interface{}) bool Len() int Same(other Set) bool Elements() []interface{} String() string }
|
注意: Set 中的 Same 方法的签名与附属于 HashSet类型的 Same 方法有所不同。这里不能再接口类型的方法的签名中包含它的实现类型。因此这里的改动如下:
1 2 3
| func (set *HashSet) Same(other Set) bool { }
|
修改了 Same 方法的签名,目的是让 *HashSet 类型成为 Set 接口类型的一个实现类型。
高级功能的方法应该适用于所有的实现类型,完全可以抽离出成为独立的函数。并且,也不应该在每个实现类型中重复地实现这些高级方法。如下为改造后的 IsSuperset 方法的声明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| func IsSuperset(one Set, other Set) bool { if one == nil || other == nil { return false } oneLen := one.Len() otherLen := other.Len() if oneLen == 0 || oneLen == otherLen { return false } if oneLen > 0 && otherLen == 0 { return true } for _, v := range other.Elements() { if !one.Contains(v) { return false } } return true }
|
以上就是Go语言之自定义集合Set的全部内容,希望对大家学习Go语言有所帮助。
点此查看代码github代码
参考Go并发编程实战