setmatrix.go 2.7 KB

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