set_nots.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. package set
  2. import (
  3. "fmt"
  4. "strings"
  5. )
  6. // Provides a common set baseline for both threadsafe and non-ts Sets.
  7. type set struct {
  8. m map[interface{}]struct{} // struct{} doesn't take up space
  9. }
  10. // SetNonTS defines a non-thread safe set data structure.
  11. type SetNonTS struct {
  12. set
  13. }
  14. // NewNonTS creates and initializes a new non-threadsafe Set.
  15. func newNonTS() *SetNonTS {
  16. s := &SetNonTS{}
  17. s.m = make(map[interface{}]struct{})
  18. // Ensure interface compliance
  19. var _ Interface = s
  20. return s
  21. }
  22. // Add includes the specified items (one or more) to the set. The underlying
  23. // Set s is modified. If passed nothing it silently returns.
  24. func (s *set) Add(items ...interface{}) {
  25. if len(items) == 0 {
  26. return
  27. }
  28. for _, item := range items {
  29. s.m[item] = keyExists
  30. }
  31. }
  32. // Remove deletes the specified items from the set. The underlying Set s is
  33. // modified. If passed nothing it silently returns.
  34. func (s *set) Remove(items ...interface{}) {
  35. if len(items) == 0 {
  36. return
  37. }
  38. for _, item := range items {
  39. delete(s.m, item)
  40. }
  41. }
  42. // Pop deletes and return an item from the set. The underlying Set s is
  43. // modified. If set is empty, nil is returned.
  44. func (s *set) Pop() interface{} {
  45. for item := range s.m {
  46. delete(s.m, item)
  47. return item
  48. }
  49. return nil
  50. }
  51. // Has looks for the existence of items passed. It returns false if nothing is
  52. // passed. For multiple items it returns true only if all of the items exist.
  53. func (s *set) Has(items ...interface{}) bool {
  54. // assume checked for empty item, which not exist
  55. if len(items) == 0 {
  56. return false
  57. }
  58. has := true
  59. for _, item := range items {
  60. if _, has = s.m[item]; !has {
  61. break
  62. }
  63. }
  64. return has
  65. }
  66. // Size returns the number of items in a set.
  67. func (s *set) Size() int {
  68. return len(s.m)
  69. }
  70. // Clear removes all items from the set.
  71. func (s *set) Clear() {
  72. s.m = make(map[interface{}]struct{})
  73. }
  74. // IsEmpty reports whether the Set is empty.
  75. func (s *set) IsEmpty() bool {
  76. return s.Size() == 0
  77. }
  78. // IsEqual test whether s and t are the same in size and have the same items.
  79. func (s *set) IsEqual(t Interface) bool {
  80. // Force locking only if given set is threadsafe.
  81. if conv, ok := t.(*Set); ok {
  82. conv.l.RLock()
  83. defer conv.l.RUnlock()
  84. }
  85. // return false if they are no the same size
  86. if sameSize := len(s.m) == t.Size(); !sameSize {
  87. return false
  88. }
  89. equal := true
  90. t.Each(func(item interface{}) bool {
  91. _, equal = s.m[item]
  92. return equal // if false, Each() will end
  93. })
  94. return equal
  95. }
  96. // IsSubset tests whether t is a subset of s.
  97. func (s *set) IsSubset(t Interface) (subset bool) {
  98. subset = true
  99. t.Each(func(item interface{}) bool {
  100. _, subset = s.m[item]
  101. return subset
  102. })
  103. return
  104. }
  105. // IsSuperset tests whether t is a superset of s.
  106. func (s *set) IsSuperset(t Interface) bool {
  107. return t.IsSubset(s)
  108. }
  109. // Each traverses the items in the Set, calling the provided function for each
  110. // set member. Traversal will continue until all items in the Set have been
  111. // visited, or if the closure returns false.
  112. func (s *set) Each(f func(item interface{}) bool) {
  113. for item := range s.m {
  114. if !f(item) {
  115. break
  116. }
  117. }
  118. }
  119. // Copy returns a new Set with a copy of s.
  120. func (s *set) Copy() Interface {
  121. u := newNonTS()
  122. for item := range s.m {
  123. u.Add(item)
  124. }
  125. return u
  126. }
  127. // String returns a string representation of s
  128. func (s *set) String() string {
  129. t := make([]string, 0, len(s.List()))
  130. for _, item := range s.List() {
  131. t = append(t, fmt.Sprintf("%v", item))
  132. }
  133. return fmt.Sprintf("[%s]", strings.Join(t, ", "))
  134. }
  135. // List returns a slice of all items. There is also StringSlice() and
  136. // IntSlice() methods for returning slices of type string or int.
  137. func (s *set) List() []interface{} {
  138. list := make([]interface{}, 0, len(s.m))
  139. for item := range s.m {
  140. list = append(list, item)
  141. }
  142. return list
  143. }
  144. // Merge is like Union, however it modifies the current set it's applied on
  145. // with the given t set.
  146. func (s *set) Merge(t Interface) {
  147. t.Each(func(item interface{}) bool {
  148. s.m[item] = keyExists
  149. return true
  150. })
  151. }
  152. // it's not the opposite of Merge.
  153. // Separate removes the set items containing in t from set s. Please aware that
  154. func (s *set) Separate(t Interface) {
  155. s.Remove(t.List()...)
  156. }