github.com/2lambda123/git-lfs@v2.5.2+incompatible/tools/ordered_set.go (about) 1 package tools 2 3 // OrderedSet is a unique set of strings that maintains insertion order. 4 type OrderedSet struct { 5 // s is the set of strings that we're keeping track of. 6 s []string 7 // m is a mapping of string value "s" into the index "i" that that 8 // string is present in in the given "s". 9 m map[string]int 10 } 11 12 // NewOrderedSet creates an ordered set with no values. 13 func NewOrderedSet() *OrderedSet { 14 return NewOrderedSetWithCapacity(0) 15 } 16 17 // NewOrderedSetWithCapacity creates a new ordered set with no values. The 18 // returned ordered set can be appended to "capacity" number of times before it 19 // grows internally. 20 func NewOrderedSetWithCapacity(capacity int) *OrderedSet { 21 return &OrderedSet{ 22 s: make([]string, 0, capacity), 23 m: make(map[string]int, capacity), 24 } 25 } 26 27 // NewOrderedSetFromSlice returns a new ordered set with the elements given in 28 // the slice "s". 29 func NewOrderedSetFromSlice(s []string) *OrderedSet { 30 set := NewOrderedSetWithCapacity(len(s)) 31 for _, e := range s { 32 set.Add(e) 33 } 34 35 return set 36 } 37 38 // Add adds the given element "i" to the ordered set, unless the element is 39 // already present. It returns whether or not the element was added. 40 func (s *OrderedSet) Add(i string) bool { 41 if _, ok := s.m[i]; ok { 42 return false 43 } 44 45 s.s = append(s.s, i) 46 s.m[i] = len(s.s) - 1 47 48 return true 49 } 50 51 // Contains returns whether or not the given "i" is contained in this ordered 52 // set. It is a constant-time operation. 53 func (s *OrderedSet) Contains(i string) bool { 54 if _, ok := s.m[i]; ok { 55 return true 56 } 57 return false 58 } 59 60 // ContainsAll returns whether or not all of the given items in "i" are present 61 // in the ordered set. 62 func (s *OrderedSet) ContainsAll(i ...string) bool { 63 for _, item := range i { 64 if !s.Contains(item) { 65 return false 66 } 67 } 68 return true 69 } 70 71 // IsSubset returns whether other is a subset of this ordered set. In other 72 // words, it returns whether or not all of the elements in "other" are also 73 // present in this set. 74 func (s *OrderedSet) IsSubset(other *OrderedSet) bool { 75 for _, i := range other.s { 76 if !s.Contains(i) { 77 return false 78 } 79 } 80 return true 81 } 82 83 // IsSuperset returns whether or not this set is a superset of "other". In other 84 // words, it returns whether or not all of the elements in this set are also in 85 // the set "other". 86 func (s *OrderedSet) IsSuperset(other *OrderedSet) bool { 87 return other.IsSubset(s) 88 } 89 90 // Union returns a union of this set with the given set "other". It returns the 91 // items that are in either set while maintaining uniqueness constraints. It 92 // preserves ordered within each set, and orders the elements in this set before 93 // the elements in "other". 94 // 95 // It is an O(n+m) operation. 96 func (s *OrderedSet) Union(other *OrderedSet) *OrderedSet { 97 union := NewOrderedSetWithCapacity(other.Cardinality() + s.Cardinality()) 98 99 for _, e := range s.s { 100 union.Add(e) 101 } 102 for _, e := range other.s { 103 union.Add(e) 104 } 105 106 return union 107 } 108 109 // Intersect returns the elements that are in both this set and then given 110 // "ordered" set. It is an O(min(n, m)) (in other words, O(n)) operation. 111 func (s *OrderedSet) Intersect(other *OrderedSet) *OrderedSet { 112 intersection := NewOrderedSetWithCapacity(MinInt( 113 s.Cardinality(), other.Cardinality())) 114 115 if s.Cardinality() < other.Cardinality() { 116 for _, elem := range s.s { 117 if other.Contains(elem) { 118 intersection.Add(elem) 119 } 120 } 121 } else { 122 for _, elem := range other.s { 123 if s.Contains(elem) { 124 intersection.Add(elem) 125 } 126 } 127 } 128 129 return intersection 130 } 131 132 // Difference returns the elements that are in this set, but not included in 133 // other. 134 func (s *OrderedSet) Difference(other *OrderedSet) *OrderedSet { 135 diff := NewOrderedSetWithCapacity(s.Cardinality()) 136 for _, e := range s.s { 137 if !other.Contains(e) { 138 diff.Add(e) 139 } 140 } 141 142 return diff 143 } 144 145 // SymmetricDifference returns the elements that are not present in both sets. 146 func (s *OrderedSet) SymmetricDifference(other *OrderedSet) *OrderedSet { 147 left := s.Difference(other) 148 right := other.Difference(s) 149 150 return left.Union(right) 151 } 152 153 // Clear removes all elements from this set. 154 func (s *OrderedSet) Clear() { 155 s.s = make([]string, 0) 156 s.m = make(map[string]int, 0) 157 } 158 159 // Remove removes the given element "i" from this set. 160 func (s *OrderedSet) Remove(i string) { 161 idx, ok := s.m[i] 162 if !ok { 163 return 164 } 165 166 rest := MinInt(idx+1, len(s.s)-1) 167 168 s.s = append(s.s[:idx], s.s[rest:]...) 169 for _, e := range s.s[rest:] { 170 s.m[e] = s.m[e] - 1 171 } 172 delete(s.m, i) 173 } 174 175 // Cardinality returns the cardinality of this set. 176 func (s *OrderedSet) Cardinality() int { 177 return len(s.s) 178 } 179 180 // Iter returns a channel which yields the elements in this set in insertion 181 // order. 182 func (s *OrderedSet) Iter() <-chan string { 183 c := make(chan string) 184 go func() { 185 for _, i := range s.s { 186 c <- i 187 } 188 close(c) 189 }() 190 191 return c 192 } 193 194 // Equal returns whether this element has the same number, identity and ordering 195 // elements as given in "other". 196 func (s *OrderedSet) Equal(other *OrderedSet) bool { 197 if s.Cardinality() != other.Cardinality() { 198 return false 199 } 200 201 for e, i := range s.m { 202 if ci, ok := other.m[e]; !ok || ci != i { 203 return false 204 } 205 } 206 207 return true 208 } 209 210 // Clone returns a deep copy of this set. 211 func (s *OrderedSet) Clone() *OrderedSet { 212 clone := NewOrderedSetWithCapacity(s.Cardinality()) 213 for _, i := range s.s { 214 clone.Add(i) 215 } 216 return clone 217 }