1 // Package set provides both threadsafe and non-threadsafe implementations of
2 // a generic set data structure. In the threadsafe set, safety encompasses all
3 // operations on one set. Operations on multiple sets are consistent in that
4 // the elements of each set used was valid at exactly one point in time
5 // between the start and the end of the operation.
8 // Interface is describing a Set. Sets are an unordered, unique list of values.
9 type Interface interface {
10 New(items ...interface{}) Interface
11 Add(items ...interface{})
12 Remove(items ...interface{})
14 Has(items ...interface{}) bool
18 IsEqual(s Interface) bool
19 IsSubset(s Interface) bool
20 IsSuperset(s Interface) bool
21 Each(func(interface{}) bool)
29 // helpful to not write everywhere struct{}{}
30 var keyExists = struct{}{}
32 // Union is the merger of multiple sets. It returns a new set with all the
33 // elements present in all the sets that are passed.
35 // The dynamic type of the returned set is determined by the first passed set's
36 // implementation of the New() method.
37 func Union(set1, set2 Interface, sets ...Interface) Interface {
39 set2.Each(func(item interface{}) bool {
43 for _, set := range sets {
44 set.Each(func(item interface{}) bool {
53 // Difference returns a new set which contains items which are in in the first
54 // set but not in the others. Unlike the Difference() method you can use this
55 // function separately with multiple sets.
56 func Difference(set1, set2 Interface, sets ...Interface) Interface {
59 for _, set := range sets {
60 s.Separate(set) // seperate is thread safe
65 // Intersection returns a new set which contains items that only exist in all given sets.
66 func Intersection(set1, set2 Interface, sets ...Interface) Interface {
67 all := Union(set1, set2, sets...)
68 result := Union(set1, set2, sets...)
70 all.Each(func(item interface{}) bool {
71 if !set1.Has(item) || !set2.Has(item) {
75 for _, set := range sets {
85 // SymmetricDifference returns a new set which s is the difference of items which are in
86 // one of either, but not in both.
87 func SymmetricDifference(s Interface, t Interface) Interface {
93 // StringSlice is a helper function that returns a slice of strings of s. If
94 // the set contains mixed types of items only items of type string are returned.
95 func StringSlice(s Interface) []string {
96 slice := make([]string, 0)
97 for _, item := range s.List() {
98 v, ok := item.(string)
103 slice = append(slice, v)
108 // IntSlice is a helper function that returns a slice of ints of s. If
109 // the set contains mixed types of items only items of type int are returned.
110 func IntSlice(s Interface) []int {
111 slice := make([]int, 0)
112 for _, item := range s.List() {
118 slice = append(slice, v)