|
2 | 2 | [](https://goreportcard.com/report/github.com/deckarep/golang-set) |
3 | 3 | [](http://godoc.org/github.com/deckarep/golang-set) |
4 | 4 |
|
5 | | -## golang-set |
6 | | - |
7 | | -## Features (as of 12/17/2021) |
8 | | -*New and improved* built with **Generics**! |
9 | | -This is in *ALPHA* quality state, and pending some feedback from the community. |
| 5 | +# golang-set |
10 | 6 |
|
11 | 7 | The missing set collection for the Go language. Until Go has sets built-in...use this. |
12 | 8 |
|
13 | | -Coming from Python one of the things I miss is the superbly wonderful set collection. This is my attempt to mimic the primary features of the set from Python. |
14 | | -You can of course argue that there is no need for a set in Go, otherwise the creators would have added one to the standard library. To those I say simply ignore this repository |
15 | | -and carry-on and to the rest that find this useful please contribute in helping me make it better by: |
| 9 | +Coming from Python one of the things I miss is the superbly wonderful set collection. This is my attempt to mimic the primary features of the set collection from Python. |
| 10 | +You can of course argue that there is no need for a set in Go, otherwise the creators would have added one to the standard library. To those I say simply ignore this repository and carry-on and to the rest that find this useful please contribute in helping me make it better by contributing with suggestions or PRs. |
16 | 11 |
|
17 | | -* Helping to make more idiomatic improvements to the code. |
18 | | -* Helping to increase the performance of it. ~~(So far, no attempt has been made, but since it uses a map internally, I expect it to be mostly performant.)~~ |
19 | | -* Helping to make the unit-tests more robust and kick-ass. |
20 | | -* Helping to fill in the [documentation.](http://godoc.org/github.com/deckarep/golang-set) |
21 | | -* Simply offering feedback and suggestions. (Positive, constructive feedback is appreciated.) |
| 12 | +## Features |
22 | 13 |
|
23 | | -I have to give some credit for helping seed the idea with this post on [stackoverflow.](http://programmers.stackexchange.com/questions/177428/sets-data-structure-in-golang) |
| 14 | +* *NEW* [Generics](https://go.dev/doc/tutorial/generics) based implementation (requires [Go 1.18beta1](https://go.dev/blog/go1.18beta1) or higher) |
| 15 | +* One common interface to both implementations |
| 16 | + * a non threadsafe implementation designed for performance |
| 17 | + * a threadsafe implementation designed for concurrent use |
| 18 | +* Feature complete set implementation modeled after [Python's set implementation](https://docs.python.org/3/library/stdtypes.html#set). |
| 19 | +* Exhaustive unit-test and benchmark suite |
24 | 20 |
|
25 | | -*Update* - as of 3/9/2014, you can use a compile-time generic version of this package in the [gen](http://clipperhouse.github.io/gen/) framework. This framework allows you to use the golang-set in a completely generic and type-safe way by allowing you to generate a supporting .go file based on your custom types. |
| 21 | +## Trusted by |
26 | 22 |
|
27 | | -## Features (as of 9/22/2014) |
| 23 | +This package is trusted by many companies and thousands of open-source packages. Here are just a few sample users of this package. |
28 | 24 |
|
29 | | -* a CartesianProduct() method has been added with unit-tests: [Read more about the cartesian product](http://en.wikipedia.org/wiki/Cartesian_product) |
| 25 | +* Open source projects |
| 26 | + * Ethereum |
| 27 | + * Docker |
| 28 | + * 1Password |
| 29 | + * etc |
| 30 | +* Companies |
| 31 | + * X |
| 32 | + * Y |
| 33 | + * Z |
30 | 34 |
|
31 | | -## Features (as of 9/15/2014) |
| 35 | +## Usage |
32 | 36 |
|
33 | | -* a PowerSet() method has been added with unit-tests: [Read more about the Power set](http://en.wikipedia.org/wiki/Power_set) |
| 37 | +The code below demonstrates how a Set collection can better manage data and actually minimize boilerplate and needless loops in code. This package now fully supports *generic* syntax so you are now able to instantiate a collection for any [comparable](https://flaviocopes.com/golang-comparing-values/) type object. |
34 | 38 |
|
35 | | -## Features (as of 4/22/2014) |
| 39 | +What is considered comparable in Go? |
| 40 | +* `Booleans`, `integers`, `strings`, `floats` or basically primitive types. |
| 41 | +* `Pointers` |
| 42 | +* `Arrays` |
| 43 | +* `Struct's` if *all* of their fields are also comparable |
36 | 44 |
|
37 | | -* One common interface to both implementations |
38 | | -* Two set implementations to choose from |
39 | | - * a thread-safe implementation designed for concurrent use |
40 | | - * a non-thread-safe implementation designed for performance |
41 | | -* 75 benchmarks for both implementations |
42 | | -* 35 unit tests for both implementations |
43 | | -* 14 concurrent tests for the thread-safe implementation |
| 45 | +Using this library is as simple as creating either a threadsafe or non-threadsafe set and providing a `comparable` type for instantiation of the collection. |
44 | 46 |
|
| 47 | +```go |
| 48 | +// Syntax example, doesn't compile. |
| 49 | +mySet := mapset.NewSet[T]() // where T is some concrete comparable type. |
45 | 50 |
|
| 51 | +// Therefore this code creates an int set |
| 52 | +mySet := mapset.NewSet[int]() |
46 | 53 |
|
47 | | -Please see the unit test file for additional usage examples. The Python set documentation will also do a better job than I can of explaining how a set typically [works.](http://docs.python.org/2/library/sets.html) Please keep in mind |
48 | | -however that the Python set is a built-in type and supports additional features and syntax that make it awesome. |
| 54 | +// Or perhaps you want a string set |
| 55 | +mySet := mapset.NewSet[string]() |
49 | 56 |
|
50 | | -## Examples but not exhaustive: |
| 57 | +type myStruct { |
| 58 | + name string |
| 59 | + age uint8 |
| 60 | +} |
51 | 61 |
|
52 | | -```go |
53 | | -requiredClasses := mapset.NewSet() |
54 | | -requiredClasses.Add("Cooking") |
55 | | -requiredClasses.Add("English") |
56 | | -requiredClasses.Add("Math") |
57 | | -requiredClasses.Add("Biology") |
| 62 | +// Alternatively a set of structs |
| 63 | +mySet := mapset.NewSet[myStruct]() |
58 | 64 |
|
59 | | -scienceSlice := []interface{}{"Biology", "Chemistry"} |
60 | | -scienceClasses := mapset.NewSetFromSlice(scienceSlice) |
| 65 | +// Lastly a set that can hold anything using the any or empty interface keyword: interface{}. This is effectively removes type safety. |
| 66 | +mySet := mapset.NewSet[any]() |
| 67 | +``` |
61 | 68 |
|
62 | | -electiveClasses := mapset.NewSet() |
63 | | -electiveClasses.Add("Welding") |
64 | | -electiveClasses.Add("Music") |
65 | | -electiveClasses.Add("Automotive") |
| 69 | +## Comprehensive Example |
66 | 70 |
|
67 | | -bonusClasses := mapset.NewSet() |
68 | | -bonusClasses.Add("Go Programming") |
69 | | -bonusClasses.Add("Python Programming") |
| 71 | +```go |
| 72 | +package main |
| 73 | + |
| 74 | +import ( |
| 75 | + "fmt" |
| 76 | + mapset "github.com/deckarep/golang-set" |
| 77 | +) |
| 78 | + |
| 79 | +func main() { |
| 80 | + // Create a string-based set of required classes. |
| 81 | + required := mapset.NewSet[string]() |
| 82 | + required.Add("cooking") |
| 83 | + required.Add("english") |
| 84 | + required.Add("math") |
| 85 | + required.Add("biology") |
| 86 | + |
| 87 | + // Create a string-based set of science classes. |
| 88 | + sciences := mapset.NewSet[string]() |
| 89 | + sciences.Add("biology") |
| 90 | + sciences.Add("chemistry") |
| 91 | + |
| 92 | + // Create a string-based set of electives. |
| 93 | + electives := mapset.NewSet[string]() |
| 94 | + electives.Add("welding") |
| 95 | + electives.Add("music") |
| 96 | + electives.Add("automotive") |
| 97 | + |
| 98 | + // Create a string-based set of bonus programming classes. |
| 99 | + bonus := mapset.NewSet[string]() |
| 100 | + bonus.Add("beginner go") |
| 101 | + bonus.Add("python for dummies") |
| 102 | +} |
| 103 | +``` |
70 | 104 |
|
71 | | -//Show me all the available classes I can take |
72 | | -allClasses := requiredClasses.Union(scienceClasses).Union(electiveClasses).Union(bonusClasses) |
73 | | -fmt.Println(allClasses) //Set{Cooking, English, Math, Chemistry, Welding, Biology, Music, Automotive, Go Programming, Python Programming} |
| 105 | +Create a set of all unique classes. |
| 106 | +Sets will *automatically* deduplicate the same data. |
74 | 107 |
|
| 108 | +```go |
| 109 | + all := required |
| 110 | + .Union(sciences) |
| 111 | + .Union(electives) |
| 112 | + .Union(bonus) |
| 113 | + |
| 114 | + fmt.Println(all) |
| 115 | +``` |
75 | 116 |
|
76 | | -//Is cooking considered a science class? |
77 | | -fmt.Println(scienceClasses.Contains("Cooking")) //false |
| 117 | +Output: |
| 118 | +```sh |
| 119 | +Set{cooking, english, math, chemistry, welding, biology, music, automotive, beginner go, python for dummies} |
| 120 | +``` |
78 | 121 |
|
79 | | -//Show me all classes that are not science classes, since I hate science. |
80 | | -fmt.Println(allClasses.Difference(scienceClasses)) //Set{Music, Automotive, Go Programming, Python Programming, Cooking, English, Math, Welding} |
| 122 | +Is cooking considered a science class? |
| 123 | +```go |
| 124 | +result := sciences.Contains("cooking") |
| 125 | +fmt.Println(result) |
| 126 | +``` |
81 | 127 |
|
82 | | -//Which science classes are also required classes? |
83 | | -fmt.Println(scienceClasses.Intersect(requiredClasses)) //Set{Biology} |
| 128 | +Output: |
| 129 | +```false |
| 130 | +false |
| 131 | +``` |
84 | 132 |
|
85 | | -//How many bonus classes do you offer? |
86 | | -fmt.Println(bonusClasses.Cardinality()) //2 |
| 133 | +Show me all classes that are not science classes, since I don't enjoy science. |
| 134 | +```go |
| 135 | +notScience := all.Difference(sciences) |
| 136 | +fmt.Println(notScience) |
| 137 | +``` |
87 | 138 |
|
88 | | -//Do you have the following classes? Welding, Automotive and English? |
89 | | -fmt.Println(allClasses.IsSuperset(mapset.NewSetFromSlice([]interface{}{"Welding", "Automotive", "English"}))) //true |
| 139 | +```sh |
| 140 | +Set{ music, automotive, beginner go, python for dummies, cooking, english, math, welding } |
90 | 141 | ``` |
91 | 142 |
|
92 | | -Thanks! |
| 143 | +Which science classes are also required classes? |
| 144 | +```go |
| 145 | +reqScience := sciences.Intersect(required) |
| 146 | +``` |
93 | 147 |
|
94 | | --Ralph |
| 148 | +Output: |
| 149 | +```sh |
| 150 | +Set{biology} |
| 151 | +``` |
| 152 | + |
| 153 | +How many bonus classes do you offer? |
| 154 | +```go |
| 155 | +fmt.Println(bonus.Cardinality()) |
| 156 | +``` |
| 157 | +Output: |
| 158 | +```sh |
| 159 | +2 |
| 160 | +``` |
95 | 161 |
|
96 | | -[](https://bitdeli.com/free "Bitdeli Badge") |
| 162 | +Thanks for visiting! |
97 | 163 |
|
98 | | -[](https://github.com/igrigorik/ga-beacon) |
| 164 | +-deckarep |
0 commit comments