github.com/kaydxh/golang@v0.0.131/go/container/set/set_string.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  	"reflect"
    26  	"sort"
    27  )
    28  
    29  type Empty struct{}
    30  
    31  // sets.String is a set of strings, implemented via map[string]struct{} for minimal memory consumption.
    32  type String map[string]Empty
    33  
    34  // NewString creates a String from a list of values.
    35  func NewString(items ...string) String {
    36  	ss := String{}
    37  	ss.Insert(items...)
    38  	return ss
    39  }
    40  
    41  // StringKeySet creates a String from a keys of a map[string](? extends interface{}).
    42  // If the value passed in is not actually a map, this will panic.
    43  func StringKeySet(theMap interface{}) String {
    44  	v := reflect.ValueOf(theMap)
    45  	ret := String{}
    46  
    47  	for _, keyValue := range v.MapKeys() {
    48  		ret.Insert(keyValue.Interface().(string))
    49  	}
    50  	return ret
    51  }
    52  
    53  // Insert adds items to the set.
    54  func (s String) Insert(items ...string) String {
    55  	for _, item := range items {
    56  		s[item] = Empty{}
    57  	}
    58  	return s
    59  }
    60  
    61  // Delete removes all items from the set.
    62  func (s String) Delete(items ...string) String {
    63  	for _, item := range items {
    64  		delete(s, item)
    65  	}
    66  	return s
    67  }
    68  
    69  // Has returns true if and only if item is contained in the set.
    70  func (s String) Has(item string) bool {
    71  	_, contained := s[item]
    72  	return contained
    73  }
    74  
    75  // HasAll returns true if and only if all items are contained in the set.
    76  func (s String) HasAll(items ...string) bool {
    77  	for _, item := range items {
    78  		if !s.Has(item) {
    79  			return false
    80  		}
    81  	}
    82  	return true
    83  }
    84  
    85  // HasAny returns true if any items are contained in the set.
    86  func (s String) HasAny(items ...string) bool {
    87  	for _, item := range items {
    88  		if s.Has(item) {
    89  			return true
    90  		}
    91  	}
    92  	return false
    93  }
    94  
    95  // Difference returns a set of objects that are not in s2
    96  // For example:
    97  // s1 = {a1, a2, a3}
    98  // s2 = {a1, a2, a4, a5}
    99  // s1.Difference(s2) = {a3}
   100  // s2.Difference(s1) = {a4, a5}
   101  func (s String) Difference(s2 String) String {
   102  	result := NewString()
   103  	for key := range s {
   104  		if !s2.Has(key) {
   105  			result.Insert(key)
   106  		}
   107  	}
   108  	return result
   109  }
   110  
   111  // Union returns a new set which includes items in either s1 or s2.
   112  // For example:
   113  // s1 = {a1, a2}
   114  // s2 = {a3, a4}
   115  // s1.Union(s2) = {a1, a2, a3, a4}
   116  // s2.Union(s1) = {a1, a2, a3, a4}
   117  func (s1 String) Union(s2 String) String {
   118  	result := NewString()
   119  	for key := range s1 {
   120  		result.Insert(key)
   121  	}
   122  	for key := range s2 {
   123  		result.Insert(key)
   124  	}
   125  	return result
   126  }
   127  
   128  // Intersection returns a new set which includes the item in BOTH s1 and s2
   129  // For example:
   130  // s1 = {a1, a2}
   131  // s2 = {a2, a3}
   132  // s1.Intersection(s2) = {a2}
   133  func (s1 String) Intersection(s2 String) String {
   134  	var walk, other String
   135  	result := NewString()
   136  	if s1.Len() < s2.Len() {
   137  		walk = s1
   138  		other = s2
   139  	} else {
   140  		walk = s2
   141  		other = s1
   142  	}
   143  	for key := range walk {
   144  		if other.Has(key) {
   145  			result.Insert(key)
   146  		}
   147  	}
   148  	return result
   149  }
   150  
   151  // IsSuperset returns true if and only if s1 is a superset of s2.
   152  func (s1 String) IsSuperset(s2 String) bool {
   153  	for item := range s2 {
   154  		if !s1.Has(item) {
   155  			return false
   156  		}
   157  	}
   158  	return true
   159  }
   160  
   161  // Equal returns true if and only if s1 is equal (as a set) to s2.
   162  // Two sets are equal if their membership is identical.
   163  // (In practice, this means same elements, order doesn't matter)
   164  func (s1 String) Equal(s2 String) bool {
   165  	return len(s1) == len(s2) && s1.IsSuperset(s2)
   166  }
   167  
   168  type sortableSliceOfString []string
   169  
   170  func (s sortableSliceOfString) Len() int           { return len(s) }
   171  func (s sortableSliceOfString) Less(i, j int) bool { return lessString(s[i], s[j]) }
   172  func (s sortableSliceOfString) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
   173  
   174  // List returns the contents as a sorted string slice.
   175  func (s String) List() []string {
   176  	res := make(sortableSliceOfString, 0, len(s))
   177  	for key := range s {
   178  		res = append(res, key)
   179  	}
   180  	sort.Sort(res)
   181  	return []string(res)
   182  }
   183  
   184  // UnsortedList returns the slice with contents in random order.
   185  func (s String) UnsortedList() []string {
   186  	res := make([]string, 0, len(s))
   187  	for key := range s {
   188  		res = append(res, key)
   189  	}
   190  	return res
   191  }
   192  
   193  // Returns a single element from the set.
   194  func (s String) PopAny() (string, bool) {
   195  	for key := range s {
   196  		s.Delete(key)
   197  		return key, true
   198  	}
   199  	var zeroValue string
   200  	return zeroValue, false
   201  }
   202  
   203  // Len returns the size of the set.
   204  func (s String) Len() int {
   205  	return len(s)
   206  }
   207  
   208  func lessString(lhs, rhs string) bool {
   209  	return lhs < rhs
   210  }