github.com/blend/go-sdk@v1.20240719.1/collections/set.go (about)

     1  /*
     2  
     3  Copyright (c) 2024 - Present. Blend Labs, Inc. All rights reserved
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file.
     5  
     6  */
     7  
     8  package collections
     9  
    10  import (
    11  	"fmt"
    12  	"strings"
    13  )
    14  
    15  // NewSet creates a new set from a list of values.
    16  func NewSet[T comparable](values ...T) Set[T] {
    17  	output := Set[T](make(map[T]struct{}))
    18  	for _, v := range values {
    19  		output[v] = struct{}{}
    20  	}
    21  	return output
    22  }
    23  
    24  // Set is a generic implementation of a set data structure.
    25  type Set[T comparable] map[T]struct{}
    26  
    27  // Add adds an element to the set, replacing a previous value.
    28  func (s Set[T]) Add(i T) {
    29  	s[i] = struct{}{}
    30  }
    31  
    32  // Remove removes an element from the set.
    33  func (s Set[T]) Remove(i T) {
    34  	delete(s, i)
    35  }
    36  
    37  // Contains returns if the element is in the set.
    38  func (s Set[T]) Contains(i T) bool {
    39  	_, ok := s[i]
    40  	return ok
    41  }
    42  
    43  // Len returns the number of elements in the set.
    44  func (s Set[T]) Len() int {
    45  	return len(s)
    46  }
    47  
    48  // Copy returns a new copy of the set.
    49  func (s Set[T]) Copy() Set[T] {
    50  	newSet := NewSet[T]()
    51  	for key := range s {
    52  		newSet.Add(key)
    53  	}
    54  	return newSet
    55  }
    56  
    57  // Union joins two sets together without dupes.
    58  func (s Set[T]) Union(other Set[T]) Set[T] {
    59  	union := NewSet[T]()
    60  	for k := range s {
    61  		union.Add(k)
    62  	}
    63  
    64  	for k := range other {
    65  		union.Add(k)
    66  	}
    67  	return union
    68  }
    69  
    70  // Intersect returns shared elements between two sets.
    71  func (s Set[T]) Intersect(other Set[T]) Set[T] {
    72  	intersection := NewSet[T]()
    73  	for k := range s {
    74  		if other.Contains(k) {
    75  			intersection.Add(k)
    76  		}
    77  	}
    78  	return intersection
    79  }
    80  
    81  // Subtract removes all elements of `other` set from `s`.
    82  func (s Set[T]) Subtract(other Set[T]) Set[T] {
    83  	subtracted := NewSet[T]()
    84  	for k := range s {
    85  		if !other.Contains(k) {
    86  			subtracted.Add(k)
    87  		}
    88  	}
    89  	return subtracted
    90  }
    91  
    92  // Difference returns non-shared elements between two sets.
    93  func (s Set[T]) Difference(other Set[T]) Set[T] {
    94  	difference := NewSet[T]()
    95  	for k := range s {
    96  		if !other.Contains(k) {
    97  			difference.Add(k)
    98  		}
    99  	}
   100  	for k := range other {
   101  		if !s.Contains(k) {
   102  			difference.Add(k)
   103  		}
   104  	}
   105  	return difference
   106  }
   107  
   108  // IsSubsetOf returns if a given set is a complete subset of another set,
   109  // i.e. all elements in target set are in other set.
   110  func (s Set[T]) IsSubsetOf(other Set[T]) bool {
   111  	for k := range s {
   112  		if !other.Contains(k) {
   113  			return false
   114  		}
   115  	}
   116  	return true
   117  }
   118  
   119  // AsSlice returns the set as a slice.
   120  func (s Set[T]) AsSlice() []T {
   121  	var output []T
   122  	for key := range s {
   123  		output = append(output, key)
   124  	}
   125  	return output
   126  }
   127  
   128  // String returns the set as a csv string.
   129  func (s Set[T]) String() string {
   130  	var values []string
   131  	for key := range s {
   132  		values = append(values, fmt.Sprint(key))
   133  	}
   134  	return strings.Join(values, ", ")
   135  }