github.com/wfusion/gofusion@v1.1.14/common/utils/sets.go (about)

     1  package utils
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/wfusion/gofusion/common/utils/clone"
     7  )
     8  
     9  type Set[T comparable] struct {
    10  	m       *sync.RWMutex
    11  	storage map[T]struct{}
    12  }
    13  
    14  func NewSet[T comparable](arr ...T) (s *Set[T]) {
    15  	s = &Set[T]{
    16  		m:       new(sync.RWMutex),
    17  		storage: make(map[T]struct{}, len(arr)),
    18  	}
    19  	for _, item := range arr {
    20  		s.storage[item] = struct{}{}
    21  	}
    22  	return
    23  }
    24  
    25  func (s *Set[T]) Size() int {
    26  	s.m.RLock()
    27  	defer s.m.RUnlock()
    28  	return len(s.storage)
    29  }
    30  
    31  func (s *Set[T]) Items() []T {
    32  	s.m.RLock()
    33  	defer s.m.RUnlock()
    34  
    35  	i := 0
    36  	ret := make([]T, len(s.storage))
    37  	for key := range s.storage {
    38  		ret[i] = key
    39  		i++
    40  	}
    41  	return ret
    42  }
    43  
    44  func (s *Set[T]) Insert(val ...T) *Set[T] {
    45  	s.m.Lock()
    46  	defer s.m.Unlock()
    47  
    48  	for _, v := range val {
    49  		s.storage[v] = struct{}{}
    50  	}
    51  	return s
    52  }
    53  
    54  func (s *Set[T]) Remove(val ...T) *Set[T] {
    55  	s.m.Lock()
    56  	defer s.m.Unlock()
    57  
    58  	for _, v := range val {
    59  		delete(s.storage, v)
    60  	}
    61  	return s
    62  }
    63  
    64  func (s *Set[T]) Contains(val T) bool {
    65  	s.m.RLock()
    66  	defer s.m.RUnlock()
    67  
    68  	_, ok := s.storage[val]
    69  	return ok
    70  }
    71  
    72  func (s *Set[T]) IsSubsetOf(set *Set[T]) bool {
    73  	s.m.RLock()
    74  	defer s.m.RUnlock()
    75  
    76  	for val := range s.storage {
    77  		// The empty set is a subset of all sets, but in common business use,
    78  		// there is rarely such a mathematical interpretation of the empty set being considered as
    79  		// a subset relationship, so false is chosen here.
    80  		if set == nil {
    81  			return false
    82  		}
    83  		if _, ok := set.storage[val]; !ok {
    84  			return false
    85  		}
    86  	}
    87  	return true
    88  }
    89  
    90  func (s *Set[T]) IntersectsWith(set *Set[T]) bool {
    91  	s.m.RLock()
    92  	defer s.m.RUnlock()
    93  
    94  	src := set.storage
    95  	dst := s.storage
    96  	if len(src) > len(dst) {
    97  		src, dst = dst, src
    98  	}
    99  	for val := range src {
   100  		if dst == nil {
   101  			return false
   102  		}
   103  		if _, ok := dst[val]; ok {
   104  			return true
   105  		}
   106  	}
   107  	return false
   108  }
   109  
   110  func (s *Set[T]) Reject(fn func(T) bool) *Set[T] {
   111  	s.m.Lock()
   112  	defer s.m.Unlock()
   113  
   114  	for key := range s.storage {
   115  		if fn(key) {
   116  			delete(s.storage, key)
   117  		}
   118  	}
   119  	return s
   120  }
   121  
   122  func (s *Set[T]) Filter(fn func(T) bool) *Set[T] {
   123  	s.m.Lock()
   124  	defer s.m.Unlock()
   125  
   126  	for key := range s.storage {
   127  		if !fn(key) {
   128  			delete(s.storage, key)
   129  		}
   130  	}
   131  	return s
   132  }
   133  
   134  func (s *Set[T]) Equals(o *Set[T]) bool {
   135  	s.m.RLock()
   136  	defer s.m.RUnlock()
   137  
   138  	if s == nil && o == nil {
   139  		return true
   140  	}
   141  	if s == nil || o == nil || s.Size() != o.Size() {
   142  		return false
   143  	}
   144  
   145  	for item := range s.storage {
   146  		if _, ok := o.storage[item]; !ok {
   147  			return false
   148  		}
   149  	}
   150  	for item := range o.storage {
   151  		if _, ok := s.storage[item]; !ok {
   152  			return false
   153  		}
   154  	}
   155  
   156  	return true
   157  }
   158  
   159  func (s *Set[T]) Copy() (r *Set[T]) {
   160  	if s == nil {
   161  		return
   162  	}
   163  
   164  	s.m.RLock()
   165  	defer s.m.RUnlock()
   166  	return NewSet(s.Items()...)
   167  }
   168  
   169  func (s *Set[T]) Clone() (r *Set[T]) {
   170  	if s == nil {
   171  		return
   172  	}
   173  
   174  	s.m.RLock()
   175  	defer s.m.RUnlock()
   176  
   177  	r = NewSet[T]()
   178  	for _, e := range s.Items() {
   179  		if elem, ok := any(e).(clonable[T]); ok {
   180  			r.Insert(elem.Clone())
   181  		} else {
   182  			r.Insert(clone.Clone(e))
   183  		}
   184  	}
   185  
   186  	return
   187  }