OSDN Git Service

new repo
[bytom/vapor.git] / vendor / gopkg.in / fatih / set.v0 / set.go
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.
6 package set
7
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{})
13         Pop() interface{}
14         Has(items ...interface{}) bool
15         Size() int
16         Clear()
17         IsEmpty() bool
18         IsEqual(s Interface) bool
19         IsSubset(s Interface) bool
20         IsSuperset(s Interface) bool
21         Each(func(interface{}) bool)
22         String() string
23         List() []interface{}
24         Copy() Interface
25         Merge(s Interface)
26         Separate(s Interface)
27 }
28
29 // helpful to not write everywhere struct{}{}
30 var keyExists = struct{}{}
31
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.
34 //
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 {
38         u := set1.Copy()
39         set2.Each(func(item interface{}) bool {
40                 u.Add(item)
41                 return true
42         })
43         for _, set := range sets {
44                 set.Each(func(item interface{}) bool {
45                         u.Add(item)
46                         return true
47                 })
48         }
49
50         return u
51 }
52
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 {
57         s := set1.Copy()
58         s.Separate(set2)
59         for _, set := range sets {
60                 s.Separate(set) // seperate is thread safe
61         }
62         return s
63 }
64
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...)
69
70         all.Each(func(item interface{}) bool {
71                 if !set1.Has(item) || !set2.Has(item) {
72                         result.Remove(item)
73                 }
74
75                 for _, set := range sets {
76                         if !set.Has(item) {
77                                 result.Remove(item)
78                         }
79                 }
80                 return true
81         })
82         return result
83 }
84
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 {
88         u := Difference(s, t)
89         v := Difference(t, s)
90         return Union(u, v)
91 }
92
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)
99                 if !ok {
100                         continue
101                 }
102
103                 slice = append(slice, v)
104         }
105         return slice
106 }
107
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() {
113                 v, ok := item.(int)
114                 if !ok {
115                         continue
116                 }
117
118                 slice = append(slice, v)
119         }
120         return slice
121 }