耐心和持久胜过激烈和狂热。
哈喽大家好,我是陈明勇,本文分享的内容是巧用 Go Map 特性对数组或切片进行去重。如果本文对你有帮助,不妨点个赞,如果你是 Go 语言初学者,不妨点个关注,一起成长一起进步,如果本文有错误的地方,欢迎指出!
前言
在其他语言里(如 Java
)使用过 Set
集合的小伙伴都知道,它的一个特点就是集合里的元素是不重复的。在一些需要去重场景中,我们可以使用 Set
这种数据结构去存储数据,达到去重的目的。而在 Go
语言里面,是没有 Set
这种数据类型的。如果我们想利用无重复元素的数据结构对数组或切片去重,可以使用 Go
的复合数据类型 Map
去构建 Set
集合,对数组或切片进行去重。因为 Map
中的 key
是唯一的,如果不了解 Map
的小伙伴,可以看看我之前的文章。
使用 Map 构建 Set
type MySet map[any]struct{} 复制代码
定义一个自定义类型 MySet
,具有 map[any]strcut{}
的特性。
map
的key
是any
类型,任何类型都可以当做map
的key
;map
的value
是struct{}
类型,为什么会用结构体类型?是因为后面添加k-v
键值对时,指定的value
为 空结构体strcut{}{}
,fmt.Println(unsafe.Sizeof(struct{}{})) // 0
空结构体是不占用内存空间的。
对数组或切片去重
import "fmt" type MySet map[any]struct{} func main() { s1 := []int{1, 1, 2, 3} fmt.Println(duplicateRemoving(s1)) // [1 2 3] s2 := []string{"a", "b", "c", "a"} fmt.Println(duplicateRemoving(s2)) // [a b c] } func duplicateRemoving[T any](s []T) []T { res := make([]T, 0, len(s)) mySet := make(MySet) for _, t := range s { if _, ok := mySet[t]; !ok { res = append(res, t) mySet[t] = struct{}{} } } return res } 复制代码
核心思路
- 定义一个新的切片
res
,为去重后的切片;定义一个MySet
类型的变量mySet
,用于判断元素是否重复; - 遍历原切片
s
,首先判断mySet
里是否存在以切片s
的元素t
为key
的键值对,如果不存在,往新切片res
添加元素t
,往mySet
里添加键值对t → struct{}{}
,否则说明元素重复,不做添加操作; - 返回去重后的新切片。
小结
本文介绍了如何利用 Go
的复合数据类型 Map
的特性对数组或切片进行去重。值得注意的一个地方是,在使用 Map
构建 Set
时,Value
的数据类型指定为 struct{}
,原因是后面在添加键值对的时候,指定的 Value
为空结构体 strcut{}{}
,空结构体不占用内存空间。