setmatrix.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package setmatrix
  2. import (
  3. "sync"
  4. mapset "github.com/deckarep/golang-set/v2"
  5. )
  6. // SetMatrix is a map of Sets.
  7. // The zero value is an empty set matrix ready to use.
  8. //
  9. // SetMatrix values are safe for concurrent use.
  10. type SetMatrix[T comparable] struct {
  11. matrix map[string]mapset.Set[T]
  12. mu sync.Mutex
  13. }
  14. // Get returns the members of the set for a specific key as a slice.
  15. func (s *SetMatrix[T]) Get(key string) ([]T, bool) {
  16. s.mu.Lock()
  17. defer s.mu.Unlock()
  18. set, ok := s.matrix[key]
  19. if !ok {
  20. return nil, ok
  21. }
  22. return set.ToSlice(), ok
  23. }
  24. // Contains is used to verify if an element is in a set for a specific key.
  25. func (s *SetMatrix[T]) Contains(key string, value T) (containsElement, setExists bool) {
  26. s.mu.Lock()
  27. defer s.mu.Unlock()
  28. set, ok := s.matrix[key]
  29. if !ok {
  30. return false, ok
  31. }
  32. return set.Contains(value), ok
  33. }
  34. // Insert inserts the value in the set of a key and returns whether the value is
  35. // inserted (was not already in the set) and the number of elements in the set.
  36. func (s *SetMatrix[T]) Insert(key string, value T) (inserted bool, cardinality int) {
  37. s.mu.Lock()
  38. defer s.mu.Unlock()
  39. set, ok := s.matrix[key]
  40. if !ok {
  41. if s.matrix == nil {
  42. s.matrix = make(map[string]mapset.Set[T])
  43. }
  44. s.matrix[key] = mapset.NewThreadUnsafeSet(value)
  45. return true, 1
  46. }
  47. return set.Add(value), set.Cardinality()
  48. }
  49. // Remove removes the value in the set for a specific key.
  50. func (s *SetMatrix[T]) Remove(key string, value T) (removed bool, cardinality int) {
  51. s.mu.Lock()
  52. defer s.mu.Unlock()
  53. set, ok := s.matrix[key]
  54. if !ok {
  55. return false, 0
  56. }
  57. if set.Contains(value) {
  58. set.Remove(value)
  59. removed = true
  60. // If the set is empty remove it from the matrix
  61. if set.Cardinality() == 0 {
  62. delete(s.matrix, key)
  63. }
  64. }
  65. return removed, set.Cardinality()
  66. }
  67. // Cardinality returns the number of elements in the set for a key.
  68. func (s *SetMatrix[T]) Cardinality(key string) (cardinality int, ok bool) {
  69. s.mu.Lock()
  70. defer s.mu.Unlock()
  71. set, ok := s.matrix[key]
  72. if !ok {
  73. return 0, ok
  74. }
  75. return set.Cardinality(), ok
  76. }
  77. // String returns the string version of the set.
  78. // The empty string is returned if there is no set for key.
  79. func (s *SetMatrix[T]) String(key string) (v string, ok bool) {
  80. s.mu.Lock()
  81. defer s.mu.Unlock()
  82. set, ok := s.matrix[key]
  83. if !ok {
  84. return "", ok
  85. }
  86. return set.String(), ok
  87. }
  88. // Keys returns all the keys in the map.
  89. func (s *SetMatrix[T]) Keys() []string {
  90. s.mu.Lock()
  91. defer s.mu.Unlock()
  92. keys := make([]string, 0, len(s.matrix))
  93. for k := range s.matrix {
  94. keys = append(keys, k)
  95. }
  96. return keys
  97. }