github.com/lyft/flytestdlib@v0.3.12-0.20210213045714-8cdd111ecda1/sets/generic_set.go (about)

     1  package sets
     2  
     3  import (
     4  	"sort"
     5  )
     6  
     7  type SetObject interface {
     8  	GetID() string
     9  }
    10  
    11  type Generic map[string]SetObject
    12  
    13  // New creates a Generic from a list of values.
    14  func NewGeneric(items ...SetObject) Generic {
    15  	gs := Generic{}
    16  	gs.Insert(items...)
    17  	return gs
    18  }
    19  
    20  // Insert adds items to the set.
    21  func (g Generic) Insert(items ...SetObject) {
    22  	for _, item := range items {
    23  		g[item.GetID()] = item
    24  	}
    25  }
    26  
    27  // Delete removes all items from the set.
    28  func (g Generic) Delete(items ...SetObject) {
    29  	for _, item := range items {
    30  		delete(g, item.GetID())
    31  	}
    32  }
    33  
    34  // Has returns true if and only if item is contained in the set.
    35  func (g Generic) Has(item SetObject) bool {
    36  	_, contained := g[item.GetID()]
    37  	return contained
    38  }
    39  
    40  // HasAll returns true if and only if all items are contained in the set.
    41  func (g Generic) HasAll(items ...SetObject) bool {
    42  	for _, item := range items {
    43  		if !g.Has(item) {
    44  			return false
    45  		}
    46  	}
    47  	return true
    48  }
    49  
    50  // HasAny returns true if any items are contained in the set.
    51  func (g Generic) HasAny(items ...SetObject) bool {
    52  	for _, item := range items {
    53  		if g.Has(item) {
    54  			return true
    55  		}
    56  	}
    57  	return false
    58  }
    59  
    60  // Difference returns a set of objects that are not in s2
    61  // For example:
    62  // s1 = {a1, a2, a3}
    63  // s2 = {a1, a2, a4, a5}
    64  // s1.Difference(s2) = {a3}
    65  // s2.Difference(s1) = {a4, a5}
    66  func (g Generic) Difference(g2 Generic) Generic {
    67  	result := NewGeneric()
    68  	for _, v := range g {
    69  		if !g2.Has(v) {
    70  			result.Insert(v)
    71  		}
    72  	}
    73  	return result
    74  }
    75  
    76  // Union returns a new set which includes items in either s1 or s2.
    77  // For example:
    78  // s1 = {a1, a2}
    79  // s2 = {a3, a4}
    80  // s1.Union(s2) = {a1, a2, a3, a4}
    81  // s2.Union(s1) = {a1, a2, a3, a4}
    82  func (g Generic) Union(s2 Generic) Generic {
    83  	result := NewGeneric()
    84  	for _, v := range g {
    85  		result.Insert(v)
    86  	}
    87  	for _, v := range s2 {
    88  		result.Insert(v)
    89  	}
    90  	return result
    91  }
    92  
    93  // Intersection returns a new set which includes the item in BOTH s1 and s2
    94  // For example:
    95  // s1 = {a1, a2}
    96  // s2 = {a2, a3}
    97  // s1.Intersection(s2) = {a2}
    98  func (g Generic) Intersection(s2 Generic) Generic {
    99  	var walk, other Generic
   100  	result := NewGeneric()
   101  	if g.Len() < s2.Len() {
   102  		walk = g
   103  		other = s2
   104  	} else {
   105  		walk = s2
   106  		other = g
   107  	}
   108  	for _, v := range walk {
   109  		if other.Has(v) {
   110  			result.Insert(v)
   111  		}
   112  	}
   113  	return result
   114  }
   115  
   116  // IsSuperset returns true if and only if s1 is a superset of s2.
   117  func (g Generic) IsSuperset(s2 Generic) bool {
   118  	for _, v := range s2 {
   119  		if !g.Has(v) {
   120  			return false
   121  		}
   122  	}
   123  	return true
   124  }
   125  
   126  // Equal returns true if and only if s1 is equal (as a set) to s2.
   127  // Two sets are equal if their membership is identical.
   128  // (In practice, this means same elements, order doesn't matter)
   129  func (g Generic) Equal(s2 Generic) bool {
   130  	return len(g) == len(s2) && g.IsSuperset(s2)
   131  }
   132  
   133  type sortableSliceOfGeneric []string
   134  
   135  func (s sortableSliceOfGeneric) Len() int           { return len(s) }
   136  func (s sortableSliceOfGeneric) Less(i, j int) bool { return lessString(s[i], s[j]) }
   137  func (s sortableSliceOfGeneric) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
   138  
   139  // List returns the contents as a sorted string slice.
   140  func (g Generic) ListKeys() []string {
   141  	res := make(sortableSliceOfGeneric, 0, len(g))
   142  	for key := range g {
   143  		res = append(res, key)
   144  	}
   145  	sort.Sort(res)
   146  	return []string(res)
   147  }
   148  
   149  // List returns the contents as a sorted string slice.
   150  func (g Generic) List() []SetObject {
   151  	keys := g.ListKeys()
   152  	res := make([]SetObject, 0, len(keys))
   153  	for _, k := range keys {
   154  		s := g[k]
   155  		res = append(res, s)
   156  	}
   157  	return res
   158  }
   159  
   160  // UnsortedList returns the slice with contents in random order.
   161  func (g Generic) UnsortedListKeys() []string {
   162  	res := make([]string, 0, len(g))
   163  	for key := range g {
   164  		res = append(res, key)
   165  	}
   166  	return res
   167  }
   168  
   169  // UnsortedList returns the slice with contents in random order.
   170  func (g Generic) UnsortedList() []SetObject {
   171  	res := make([]SetObject, 0, len(g))
   172  	for _, v := range g {
   173  		res = append(res, v)
   174  	}
   175  	return res
   176  }
   177  
   178  // Returns a single element from the set.
   179  func (g Generic) PopAny() (SetObject, bool) {
   180  	for _, v := range g {
   181  		g.Delete(v)
   182  		return v, true
   183  	}
   184  	var zeroValue SetObject
   185  	return zeroValue, false
   186  }
   187  
   188  // Len returns the size of the set.
   189  func (g Generic) Len() int {
   190  	return len(g)
   191  }
   192  
   193  func lessString(lhs, rhs string) bool {
   194  	return lhs < rhs
   195  }