Skip to content

Instantly share code, notes, and snippets.

@CosmicToast
Last active January 2, 2024 19:00
Show Gist options
  • Save CosmicToast/7bbcf0cfb8ae93c9f6717eb1ef8481c0 to your computer and use it in GitHub Desktop.
Save CosmicToast/7bbcf0cfb8ae93c9f6717eb1ef8481c0 to your computer and use it in GitHub Desktop.

Revisions

  1. CosmicToast revised this gist Jan 2, 2024. 1 changed file with 11 additions and 0 deletions.
    11 changes: 11 additions & 0 deletions set.go
    Original file line number Diff line number Diff line change
    @@ -28,6 +28,17 @@ func (s *Set[T]) Clear() {
    (*s) = NewSet[T]()
    }

    // Items returns a slice of all elements currently in the set.
    // Note that unless you actually want a collection, you should call Iter or
    // Filter instead. Items calls Iter internally.
    func (s Set[T]) Items() []T {
    out := make([]T, 0, len(s))
    for v := range s.Iter() {
    out = append(out, v)
    }
    return out
    }

    func fromChan[T comparable](cs ...chan T) Set[T] {
    out := NewSet[T]()
    for _, c := range cs {
  2. CosmicToast revised this gist Jan 2, 2024. 1 changed file with 6 additions and 7 deletions.
    13 changes: 6 additions & 7 deletions set.go
    Original file line number Diff line number Diff line change
    @@ -63,12 +63,11 @@ func (s Set[T]) Size() int {
    }

    // NewSet initializes a set of a given type.
    func NewSet[T comparable]() Set[T] {
    return make(map[T]struct{})
    }

    func filternt[T comparable](v T) bool {
    return true
    // Note that if you pass any initial values, the type will be inferred.
    func NewSet[T comparable](vs ...T) Set[T] {
    var out Set[T] = make(map[T]struct{})
    out.Add(vs...)
    return out
    }

    func (s Set[T]) iter(c chan T, filter func(T)bool) {
    @@ -84,7 +83,7 @@ func (s Set[T]) iter(c chan T, filter func(T)bool) {
    // It is efficient even for very large sets.
    func (s Set[T]) Iter() chan T {
    out := make(chan T)
    go s.iter(out, filternt)
    go s.iter(out, func(_ T)bool { return true })
    return out
    }

  3. CosmicToast created this gist Jan 2, 2024.
    97 changes: 97 additions & 0 deletions set.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,97 @@
    package collect

    // Set represents a generic set of comparable elements.
    type Set[T comparable] map[T]struct{}

    // Has checks whether the set holds a given value.
    func (s Set[T]) Has(v T) bool {
    _, ok := s[v]
    return ok
    }

    // Add adds values to the set. You may add as many as you wish.
    func (s Set[T]) Add(vs ...T) {
    for _, v := range vs {
    s[v] = struct{}{}
    }
    }

    // Remove removes values from the set. You may remove as many as you wish.
    func (s Set[T]) Remove(vs ...T) {
    for _, v := range vs {
    delete(s, v)
    }
    }

    // Clear reinitializes the set.
    func (s *Set[T]) Clear() {
    (*s) = NewSet[T]()
    }

    func fromChan[T comparable](cs ...chan T) Set[T] {
    out := NewSet[T]()
    for _, c := range cs {
    for v := range c {
    out.Add(v)
    }
    }
    return out
    }

    // Difference returns a new set that holds the elements present in the receiver, but not s2.
    func (s Set[T]) Difference(s2 Set[T]) Set[T] {
    return fromChan(s.Filter(func(v T)bool {
    return !s2.Has(v)
    }))
    }

    // Intersection returns a new set that holds elements present in both sets.
    func (s Set[T]) Intersection(s2 Set[T]) Set[T] {
    return fromChan(s.Filter(func(v T)bool {
    return s2.Has(v)
    }))
    }

    // Union returns a new set that holds the elements of both sets.
    func (s Set[T]) Union(s2 Set[T]) Set[T] {
    return fromChan(s.Iter(), s2.Iter())
    }

    // Size returns how many elements are in the set.
    func (s Set[T]) Size() int {
    return len(s)
    }

    // NewSet initializes a set of a given type.
    func NewSet[T comparable]() Set[T] {
    return make(map[T]struct{})
    }

    func filternt[T comparable](v T) bool {
    return true
    }

    func (s Set[T]) iter(c chan T, filter func(T)bool) {
    for k := range s {
    if filter(k) {
    c <- k
    }
    }
    close(c)
    }

    // Iter allows you to iterate over the set.
    // It is efficient even for very large sets.
    func (s Set[T]) Iter() chan T {
    out := make(chan T)
    go s.iter(out, filternt)
    return out
    }

    // Filter is like Iter, but you only get elements that pass the filter function.
    // It is efficient even for very large sets.
    func (s Set[T]) Filter(filter func(T)bool) chan T {
    out := make(chan T)
    go s.iter(out, filter)
    return out
    }