程序员社区

Go:集合Set实现

最近发现一些公司在招微服务开发人员简介中对熟悉dapr微服务运行时有要求,这里简单介绍下:Dapr是一种可移植的,事件驱动的,无服务器运行时,用于构建跨云和边缘的分布式应用程序。能够帮助开发人员轻松构建起能够运行在云端及边缘位置的高弹性、微服务、无状态/有状态应用程序。Dapr当中包含多种编程语言与开发者框架,同时显著简化了应用程序(例如示例中提到的电子商务应用)的构建流程。详细可以去官网了解:地址:https://dapr.io

Go:集合Set实现插图
Dapr框架

本文并非介绍dapr,而是在阅读dapr源码的过程中看到里面实现集合这个数据结构使用了map来实现。分享下这个实现Idea,其源代码如下:

// 这里实现的是一个字符串集合,使用空结构体是为了节省内存
type Empty struct{}
type String map[string]Empty
// NewString 根据一个字符串切片创建集合
func NewString(items ...string) String {
   ss := String{}
   ss.Insert(items...)
   return ss
}

// StringKeySet根据一个map的key来创建字符串集合
// 如何参数不是map类型会panic
func StringKeySet(theMap interface{}) String {
   v := reflect.ValueOf(theMap)
   ret := String{}

   for _, keyValue := range v.MapKeys() {
      ret.Insert(keyValue.Interface().(string))
   }
   return ret
}

// Insert 向集合插入元素
func (s String) Insert(items ...string) String {
   for _, item := range items {
      s[item] = Empty{}
   }
   return s
}

// Delete 删除集合所有元素
func (s String) Delete(items ...string) String {
   for _, item := range items {
      delete(s, item)
   }
   return s
}

// Has 返回元素是否在集合中
func (s String) Has(item string) bool {
   _, contained := s[item]
   return contained
}

// HasAll 判断切片中元素是否都在集合中
func (s String) HasAll(items ...string) bool {
   for _, item := range items {
      if !s.Has(item) {
         return false
      }
   }
   return true
}

// HasAny 返回集合中是否包含任意切片中元素
func (s String) HasAny(items ...string) bool {
   for _, item := range items {
      if s.Has(item) {
         return true
      }
   }
   return false
}

// Difference 返回元素不在传入的另一个集合中的元素
// 例如
// s1 = {a1, a2, a3}
// s2 = {a1, a2, a4, a5}
// s1.Difference(s2) = {a3}
// s2.Difference(s1) = {a4, a5}
func (s String) Difference(s2 String) String {
   result := NewString()
   for key := range s {
      if !s2.Has(key) {
         result.Insert(key)
      }
   }
   return result
}

// Union 返回两集合并集
// For example:
// s1 = {a1, a2}
// s2 = {a3, a4}
// s1.Union(s2) = {a1, a2, a3, a4}
// s2.Union(s1) = {a1, a2, a3, a4}
func (s1 String) Union(s2 String) String {
   result := NewString()
   for key := range s1 {
      result.Insert(key)
   }
   for key := range s2 {
      result.Insert(key)
   }
   return result
}

// Intersection 返回两集合交集
// For example:
// s1 = {a1, a2}
// s2 = {a2, a3}
// s1.Intersection(s2) = {a2}
func (s1 String) Intersection(s2 String) String {
   var walk, other String
   result := NewString()
   if s1.Len() < s2.Len() {
      walk = s1
      other = s2
   } else {
      walk = s2
      other = s1
   }
   for key := range walk {
      if other.Has(key) {
         result.Insert(key)
      }
   }
   return result
}

// IsSuperset 判断集合子集
func (s1 String) IsSuperset(s2 String) bool {
   for item := range s2 {
      if !s1.Has(item) {
         return false
      }
   }
   return true
}

// Equal 判断集合相等
// 只有两个集合中的元素都相同
func (s1 String) Equal(s2 String) bool {
   return len(s1) == len(s2) && s1.IsSuperset(s2)
}

这里用map[string]struct{}结构来实现,因为空结构体不占用内存的。map的key是不同的刚好符合set的特点,操作方便。当然这里实现的是string类型的集合,其他类型也类似。

赞(0) 打赏
未经允许不得转载:IDEA激活码 » Go:集合Set实现

一个分享Java & Python知识的社区