兩種 go 實現 set 的思路, 分別是 map 和 bitset。
map 的 key 肯定是唯一的,而這恰好與 set 的特性一致,天然保證 set 中成員的唯一性。而且通過 map 實現 set,在檢查是否存在某個元素時可直接使用 _, ok := m[key] 的語法,效率高。
原文鏈接:https://studygolang.com/articles/27476?fr=sidebar
golang-set-A simple set type for the Go language. Also used by Docker, 1Password, Ethereum.
在github上已經有了一個成熟的包,名為golang-set,包中提供了線程安全和非線程安全的set。提供了五個set函數:
// NewSet創建並返回空集的引用,結果集上的操作是線程安全的 func NewSet(s ...interface{}) Set {} // NewSetFromSlice從現有切片創建並返回集合的引用,結果集上的操作是線程安全的 func NewSetFromSlice(s []interface{}) Set {} // NewSetWith創建並返回具有給定元素的新集合,結果集上的操作是線程安全的 func NewSetWith(elts ...interface{}) Set {} // NewThreadUnsafeSet創建並返回對空集的引用,結果集上的操作是非線程安全的 func NewThreadUnsafeSet() Set {} // NewThreadUnsafeSetFromSlice創建並返回對現有切片中集合的引用,結果集上的操作是非線程安全的。 func NewThreadUnsafeSetFromSlice(s []interface{}) Set {}
demo
package main import ( "fmt" "github.com/deckarep/golang-set" ) func main() { // 默認創建的線程安全的,如果無需線程安全 // 可以使用 NewThreadUnsafeSet 創建,使用方法都是一樣的。 s1 := mapset.NewSet(1, 2, 3, 4) fmt.Println("s1 contains 3: ", s1.Contains(3)) fmt.Println("s1 contains 5: ", s1.Contains(5)) // interface 參數,可以傳遞任意類型 s1.Add("poloxue") fmt.Println("s1 contains poloxue: ", s1.Contains("poloxue")) s1.Remove(3) fmt.Println("s1 contains 3: ", s1.Contains(3)) s2 := mapset.NewSet(1, 3, 4, 5) // 並集 fmt.Println(s1.Union(s2)) }
運行結果:
s1 contains 3: true s1 contains 5: false s1 contains poloxue: true s1 contains 3: false Set{1, 2, 4, poloxue, 3, 5}
Examples but not exhaustive:
requiredClasses := mapset.NewSet() requiredClasses.Add("Cooking") requiredClasses.Add("English") requiredClasses.Add("Math") requiredClasses.Add("Biology") scienceSlice := []interface{}{"Biology", "Chemistry"} scienceClasses := mapset.NewSetFromSlice(scienceSlice) electiveClasses := mapset.NewSet() electiveClasses.Add("Welding") electiveClasses.Add("Music") electiveClasses.Add("Automotive") bonusClasses := mapset.NewSet() bonusClasses.Add("Go Programming") bonusClasses.Add("Python Programming") //Show me all the available classes I can take allClasses := requiredClasses.Union(scienceClasses).Union(electiveClasses).Union(bonusClasses) fmt.Println(allClasses) //Set{Cooking, English, Math, Chemistry, Welding, Biology, Music, Automotive, Go Programming, Python Programming} //Is cooking considered a science class? fmt.Println(scienceClasses.Contains("Cooking")) //false //Show me all classes that are not science classes, since I hate science. fmt.Println(allClasses.Difference(scienceClasses)) //Set{Music, Automotive, Go Programming, Python Programming, Cooking, English, Math, Welding} //Which science classes are also required classes? fmt.Println(scienceClasses.Intersect(requiredClasses)) //Set{Biology} //How many bonus classes do you offer? fmt.Println(bonusClasses.Cardinality()) //2 //Do you have the following classes? Welding, Automotive and English? fmt.Println(allClasses.IsSuperset(mapset.NewSetFromSlice([]interface{}{"Welding", "Automotive", "English"}))) //true