github.com/kaydxh/golang@v0.0.131/go/container/set/set.go (about)

     1  /*
     2   *Copyright (c) 2022, kaydxh
     3   *
     4   *Permission is hereby granted, free of charge, to any person obtaining a copy
     5   *of this software and associated documentation files (the "Software"), to deal
     6   *in the Software without restriction, including without limitation the rights
     7   *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8   *copies of the Software, and to permit persons to whom the Software is
     9   *furnished to do so, subject to the following conditions:
    10   *
    11   *The above copyright notice and this permission notice shall be included in all
    12   *copies or substantial portions of the Software.
    13   *
    14   *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15   *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16   *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17   *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18   *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19   *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    20   *SOFTWARE.
    21   */
    22  package set
    23  
    24  import (
    25  	"encoding/json"
    26  	"sort"
    27  )
    28  
    29  // type Set[type T comparable] map[T]Empty
    30  type Set[T comparable] map[T]Empty
    31  
    32  func New[T comparable](items ...T) Set[T] {
    33  	// func New[T comparable]() Set[T] {
    34  	ss := make(Set[T], len(items))
    35  	ss.Insert(items...)
    36  	return ss
    37  }
    38  
    39  // Insert adds items to the set.
    40  func (s Set[T]) Insert(items ...T) Set[T] {
    41  	for _, item := range items {
    42  		s[item] = Empty{}
    43  	}
    44  
    45  	return s
    46  }
    47  
    48  // Delete removes all items from the set.
    49  func (s Set[T]) Delete(items ...T) Set[T] {
    50  	for _, item := range items {
    51  		delete(s, item)
    52  	}
    53  	return s
    54  }
    55  
    56  // Has returns true if and only if item is contained in the set.
    57  func (s Set[T]) Has(item T) bool {
    58  	_, contained := s[item]
    59  	return contained
    60  }
    61  
    62  // HasAll returns true if and only if all items are contained in the set.
    63  func (s Set[T]) HasAll(items ...T) bool {
    64  	for _, item := range items {
    65  		if !s.Has(item) {
    66  			return false
    67  		}
    68  	}
    69  	return true
    70  }
    71  
    72  // HasAny returns true if any items are contained in the set.
    73  func (s Set[T]) HasAny(items ...T) bool {
    74  	for _, item := range items {
    75  		if s.Has(item) {
    76  			return true
    77  		}
    78  	}
    79  	return false
    80  }
    81  
    82  // Difference returns a set of objects that are not in s2
    83  // For example:
    84  // s1 = {a1, a2, a3}
    85  // s2 = {a1, a2, a4, a5}
    86  // s1.Difference(s2) = {a3}
    87  // s2.Difference(s1) = {a4, a5}
    88  func (s Set[T]) Difference(s2 Set[T]) Set[T] {
    89  	result := New[T]()
    90  	for key := range s {
    91  		if !s2.Has(key) {
    92  			result.Insert(key)
    93  		}
    94  	}
    95  	return result
    96  }
    97  
    98  // Union returns a new set which includes items in either s1 or s2.
    99  // For example:
   100  // s1 = {a1, a2}
   101  // s2 = {a3, a4}
   102  // s1.Union(s2) = {a1, a2, a3, a4}
   103  // s2.Union(s1) = {a1, a2, a3, a4}
   104  func (s1 Set[T]) Union(s2 Set[T]) Set[T] {
   105  	result := New[T]()
   106  	for key := range s1 {
   107  		result.Insert(key)
   108  	}
   109  	for key := range s2 {
   110  		result.Insert(key)
   111  	}
   112  	return result
   113  }
   114  
   115  // Intersection returns a new set which includes the item in BOTH s1 and s2
   116  // For example:
   117  // s1 = {a1, a2}
   118  // s2 = {a2, a3}
   119  // s1.Intersection(s2) = {a2}
   120  func (s1 Set[T]) Intersection(s2 Set[T]) Set[T] {
   121  	var walk, other Set[T]
   122  	result := New[T]()
   123  	if s1.Len() < s2.Len() {
   124  		walk = s1
   125  		other = s2
   126  	} else {
   127  		walk = s2
   128  		other = s1
   129  	}
   130  	for key := range walk {
   131  		if other.Has(key) {
   132  			result.Insert(key)
   133  		}
   134  	}
   135  	return result
   136  }
   137  
   138  // IsSuperset returns true if and only if s1 is a superset of s2.
   139  func (s1 Set[T]) IsSuperset(s2 Set[T]) bool {
   140  	for item := range s2 {
   141  		if !s1.Has(item) {
   142  			return false
   143  		}
   144  	}
   145  	return true
   146  }
   147  
   148  // Equal returns true if and only if s1 is equal (as a set) to s2.
   149  // Two sets are equal if their membership is identical.
   150  // (In practice, this means same elements, order doesn't matter)
   151  func (s1 Set[T]) Equal(s2 Set[T]) bool {
   152  	return len(s1) == len(s2) && s1.IsSuperset(s2)
   153  }
   154  
   155  type sortableSliceOfT[T comparable] []T
   156  
   157  func (s sortableSliceOfT[T]) Len() int           { return len(s) }
   158  func (s sortableSliceOfT[T]) Less(i, j int) bool { return lessT(s[i], s[j]) }
   159  func (s sortableSliceOfT[T]) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
   160  
   161  // List returns the contents as a sorted Object slice.
   162  func (s Set[T]) List() []T {
   163  	res := make(sortableSliceOfT[T], 0, len(s))
   164  	for key := range s {
   165  		res = append(res, key)
   166  	}
   167  	sort.Sort(res)
   168  	return []T(res)
   169  }
   170  
   171  // UnsortedList returns the slice with contents in random order.
   172  func (s Set[T]) UnsortedList() []T {
   173  	res := make([]T, 0, len(s))
   174  	for key := range s {
   175  		res = append(res, key)
   176  	}
   177  	return res
   178  }
   179  
   180  // Returns a single element from the set.
   181  func (s Set[T]) PopAny() (T, bool) {
   182  	for key := range s {
   183  		s.Delete(key)
   184  		return key, true
   185  	}
   186  	var zeroValue T
   187  	return zeroValue, false
   188  }
   189  
   190  // Len returns the size of the set.
   191  func (s Set[T]) Len() int {
   192  	return len(s)
   193  }
   194  
   195  type LesserT[T comparable] interface {
   196  	Less(a, b T) bool
   197  }
   198  
   199  func lessT[T comparable](lhs, rhs T) bool {
   200  	jbl, err := json.Marshal(lhs)
   201  	if err != nil {
   202  		return false
   203  	}
   204  	jbr, err := json.Marshal(rhs)
   205  	if err != nil {
   206  		return false
   207  	}
   208  
   209  	return string(jbl) < string(jbr)
   210  }