Go中如何使用set的方法示例

2020-01-28 14:08:46王振洲

一个简单例子,如下:


package main

import (
 "fmt"
)

const (
 shift = 6
 mask = 0x3f // 即0b00111111
)

type Bitset struct {
 data []int64
}

func NewBitSet(n int) *Bitset {
 // 获取位置信息
 index := n >> shift

 set := &Bitset{
 data: make([]int64, index+1),
 }

 // 根据 n 设置 bitset
 set.data[index] |= 1 << uint(n&mask)

 return set
}

func (set *Bitset) Contains(n int) bool {
 // 获取位置信息
 index := n >> shift
 return set.data[index]&(1<<uint(n&mask)) != 0
}

func main() {
 set := NewBitSet(65)
 fmt.Println("set contains 65", set.Contains(65))
 fmt.Println("set contains 64", set.Contains(64))
}

输出结果

set contains 65 true
set contains 64 false

以上的例子功能很简单,只是为了演示,只有创建 bitset 和 contains 两个功能,其他诸如添加、删除、不同 bitset 间的交、并、差还没有实现。有兴趣的朋友可以继续尝试。

其实,bitset 包也有人实现了,github地址 bit[5]。可以读读它的源码,实现思路和上面介绍差不多。

下面是一个使用案例。


package main

import (
 "fmt"

 "github.com/yourbasic/bit"
)

func main() {
 s := bit.New(2, 3, 4, 65, 128)
 fmt.Println("s contains 65", s.Contains(65))
 fmt.Println("s contains 15", s.Contains(15))

 s.Add(15)
 fmt.Println("s contains 15", s.Contains(15))

 fmt.Println("next 20 is ", s.Next(20))
 fmt.Println("prev 20 is ", s.Prev(20))

 s2 := bit.New(10, 22, 30)

 s3 := s.Or(s2)
 fmt.Println("next 20 is ", s3.Next(20))

 s3.Visit(func(n int) bool {
 fmt.Println(n)
 return false // 返回 true 表示终止遍历
 })
}

执行结果:

s contains 65 true
s contains 15 false
s contains 15 true
next 20 is 65
prev 20 is 15
next 20 is 22
2
3
4
10
15
22
30
65
128

代码的意思很好理解,就是一些增删改查和集合的操作。要注意的是,bitset 和前面的 set 的区别,bitset 的成员只能是 int 整型,没有 set 灵活。平时的使用场景也比较少,主要用在对效率和存储空间要求较高的场景。

总结

本文介绍了Go 中两种 set 的实现原理,并在此基础介绍了对应于它们的两个包简单使用。我觉得,通过这篇文章,Go 中 set 的使用,基本都可以搞定了。

除这两个包,再补充两个,zoumo/goset[6] 和 github.com/willf/bitset[7]。

参考资料

[1]2 basic set implementations: https://yourbasic.org/golang/implement-set/

[2]一篇文章: https://www.jb51.net/article/170043.htm

[3]golang-set: https://github.com/deckarep/golang-set

[4]Bitmasks, bitsets and flags: https://yourbasic.org/golang/bitmask-flag-set-clear/

[5]bit: https://github.com/yourbasic/bit

[6]zoumo/goset: https://github.com/zoumo/goset