sets

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 14, 2026 License: MIT Imports: 5 Imported by: 0

README

sets

Go Reference Github release Go Report Card Lint Status Coverage Status License

A high-performance, idiomatic Go library for set operations that follows the same design principles as the standard library's maps and slices packages.

Design Philosophy: Idiomatic Go

This library combines idiomatic Go design with practical functionality that developers need in real-world projects.

Native map at the core. Set[T] is a type alias for map[T]struct{}, not a wrapper type. All native Go map operations work out of the box: len(), clear(), delete(), for...range.

Follows standard library conventions. The API mirrors the design of maps and slices — composable functions that each do one thing well, consistent naming, variadic parameters where they make sense. No method chaining or fluent APIs.

Comprehensive. ~30 functions covering set theory, functional programming, and iterators.

Robust. Read-only functions gracefully handle nil sets, consistent with how the standard library's maps and slices packages treat nil inputs. Pre-allocated capacity for optimal performance.

Zero dependencies. Pure Go standard library only — no external dependencies to manage or security vulnerabilities to track.


Installation

go get github.com/kkhmel/sets

Requires Go 1.23+.


Usage

Quick Start
package main

import (
    "fmt"
    "github.com/kkhmel/sets"
)

func main() {
    // Create sets of user permissions
    admin := sets.From("read", "write", "delete", "admin")
    editor := sets.From("read", "write")
    viewer := sets.From("read")

    // Check permissions
    if sets.ContainsAll(admin, "delete", "admin") {
        fmt.Println("Admin has delete and admin privileges") // Output: Admin has delete and admin privileges
    }

    // Combine all unique permissions
    allPerms := sets.Union(admin, editor, viewer)
    fmt.Println("All permissions:", allPerms) // Output: All permissions: {admin, delete, read, write}

    // Find admin-exclusive permissions
    exclusive := sets.Difference(admin, editor, viewer)
    fmt.Println("Admin-only:", exclusive) // Output: Admin-only: {admin, delete}

    // Check subset relationships
    if sets.Subset(viewer, editor) {
        fmt.Println("Viewers are a subset of editors") // Output: Viewers are a subset of editors
    }
}
Guideline

Use builtin len() for size, clear() for clearing, and range for iteration. For all other operations, use sets package functions for consistency and cleaner code.

s := sets.From("a", "b", "c")

// Use native operations for these common cases
count := len(s)    // Get size
clear(s)           // Clear all elements
for e := range s { // Iterate over elements
    ...
}

// Use sets package functions for everything else -- cleaner and more consistent
items := []string{"d", "e"}
sets.Insert(s, items...)                 // Instead of: for _, e := range items { s[e] = struct{}{} }
sets.Delete(s, items...)                 // Instead of: for _, e := range items { delete(s, e) }
if sets.Contains(s, "x") { ... }         // Instead of: if _, ok := s["x"]; ok { ... }
if sets.ContainsAny(s, items...) { ... } // Instead of: manual loop with checks

But since Set[T] is a type alias for map[T]struct{}, you have full access to native Go map operations and the maps package.


Performance

The library is designed for maximum performance through several key principles:

Core Performance Principles:

  • Zero-cost abstraction: Leverages Go's highly-optimized map implementation directly
  • Zero-byte values: Uses struct{} as map value (0 bytes per element) for minimal memory footprint
  • Smart pre-allocation: Set operations pre-allocate capacity based on input sizes to minimize reallocation
  • Inlining-friendly: Simple functions are designed to be inlined by the compiler

Complexity Information: Detailed time and space complexity for each function is documented in the API documentation.

Note: Call sets.Clone() on results to reclaim excess memory if needed.


Thread Safety

  • Safe for concurrent reads — Multiple goroutines can safely read from a set simultaneously
  • Requires synchronization for writes — Use sync.RWMutex or sync.Mutex when modifying sets concurrently

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for details on how to submit pull requests, report issues, and contribute to the code.

Documentation

Overview

Package sets provides a high-performance, idiomatic Set library for Go that follows the same design principles as the standard library's maps and slices packages.

The library provides ~30 functions covering:

  • Set theory operations (Union, Intersection, Difference, etc.)
  • Functional programming (Map, Filter, Reduce)
  • Predicates and comparisons (Equal, Subset, Contains, etc.)
  • Iterator support

Zero dependencies. Pure Go standard library only.

Example
package main

import (
	"fmt"

	"github.com/kkhmel/sets"
)

func main() {
	// Create sets of user permissions
	admin := sets.From("read", "write", "delete", "admin")
	editor := sets.From("read", "write")
	viewer := sets.From("read")

	// Check permissions
	if sets.ContainsAll(admin, "delete", "admin") {
		fmt.Println("Admin has delete and admin privileges")
	}

	// Combine all unique permissions
	allPerms := sets.Union(admin, editor, viewer)
	fmt.Println("All permissions:", allPerms)

	// Find admin-exclusive permissions
	exclusive := sets.Difference(admin, editor, viewer)
	fmt.Println("Admin-only:", exclusive)

}
Output:

Admin has delete and admin privileges
All permissions: {admin, delete, read, write}
Admin-only: {admin, delete}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func All

func All[S ~map[E]struct{}, E comparable](s S) iter.Seq[E]

All returns an iterator over elements from s. The iteration order is not specified and is not guaranteed to be the same from one call to the next.

Creation: O(1) time, O(1) space. Iteration: O(len(s)) time, O(1) space.

func Chunk

func Chunk[S ~map[E]struct{}, E comparable](s S, n int) iter.Seq[S]

Chunk returns an iterator over consecutive subsets of up to n elements of s. All but the last subset will have size n. If s is empty, the sequence is empty: there is no empty set in the sequence. Chunk panics if n is less than 1.

Creation: O(1) time, O(1) space. Iteration: O(len(s)) time, O(n) space.

Example
package main

import (
	"fmt"

	"github.com/kkhmel/sets"
)

func main() {
	numbers := sets.From(1, 2, 3, 4, 5, 6, 7)
	chunkCount := 0
	for chunk := range sets.Chunk(numbers, 3) {
		chunkCount++
		fmt.Printf("Chunk %d size: %d\n", chunkCount, len(chunk))
	}

}
Output:

Chunk 1 size: 3
Chunk 2 size: 3
Chunk 3 size: 1

func Clone

func Clone[S ~map[E]struct{}, E comparable](s S) S

Clone returns a shallow copy of s. The new set is allocated with a capacity hint equal to len(s), which may help reclaim excess memory held by the original map (e.g. after many deletions).

Time complexity: O(len(s)). Space complexity: O(len(s)).

func Contains

func Contains[S ~map[E]struct{}, E comparable](s S, v E) bool

Contains reports whether v is present in s.

Time complexity: O(1). Space complexity: O(1).

func ContainsAll

func ContainsAll[S ~map[E]struct{}, E comparable](s S, v ...E) bool

ContainsAll reports whether all specified elements are present in s.

Time complexity: O(len(v)). Space complexity: O(1).

func ContainsAny

func ContainsAny[S ~map[E]struct{}, E comparable](s S, v ...E) bool

ContainsAny reports whether at least one of the specified elements is present in s.

Time complexity: O(len(v)). Space complexity: O(1).

func Copy

func Copy[S1 ~map[E]struct{}, S2 ~map[E]struct{}, E comparable](dst S1, src S2)

Copy copies all elements in src, adding them to dst.

Time complexity: O(len(src)). Space complexity: O(len(src)).

func Delete

func Delete[S ~map[E]struct{}, E comparable](s S, v ...E)

Delete deletes the specified elements from the set. If s is nil or there is no such element, delete is a no-op.

Time complexity: O(len(v)). Space complexity: O(1).

func DeleteFunc

func DeleteFunc[S ~map[E]struct{}, E comparable](s S, del func(E) bool)

DeleteFunc deletes any elements from s for which del returns true.

Time complexity: O(len(s)). Space complexity: O(1).

Example
package main

import (
	"fmt"

	"github.com/kkhmel/sets"
)

func main() {
	numbers := sets.From(1, 2, 3, 4, 5)
	sets.DeleteFunc(numbers, func(e int) bool { return e%2 == 0 })
	fmt.Println(numbers)

}
Output:

{1, 3, 5}

func Equal

func Equal[S1, S2 ~map[E]struct{}, E comparable](s1 S1, s2 S2) bool

Equal reports whether two sets contain the same elements. Elements are compared using ==.

Time complexity: O(len(s1)). Space complexity: O(1).

func Every

func Every[S ~map[E]struct{}, E comparable](s S, f func(E) bool) bool

Every reports whether all elements e of s satisfy f(e).

Time complexity: O(len(s)). Space complexity: O(1).

Example
package main

import (
	"fmt"

	"github.com/kkhmel/sets"
)

func main() {
	mixed := sets.From(1, 2, 3, 4)
	allPositive := sets.Every(mixed, func(e int) bool { return e > 0 })
	fmt.Println("All positive:", allPositive)

}
Output:

All positive: true

func Grow

func Grow[S ~map[E]struct{}, E comparable](s S, n int) S

Grow returns a new set with capacity increased to guarantee space for n more elements without another allocation. After Grow(n), at least n elements can be appended to the set without another allocation. If n is negative or too large to allocate the memory, Grow panics.

Time complexity: O(len(s)). Space complexity: O(len(s) + n).

func Insert

func Insert[S ~map[E]struct{}, E comparable](s S, v ...E)

Insert inserts the given elements into the set. Elements already present in the set are ignored.

Time complexity: O(len(v)). Space complexity: O(1).

func InsertSeq

func InsertSeq[S ~map[E]struct{}, E comparable](s S, seq iter.Seq[E])

InsertSeq inserts the elements from seq to s. Duplicate elements are ignored.

Time complexity: O(n). Space complexity: O(n). n is the number of seq elements.

func Overlaps

func Overlaps[S ~map[E]struct{}, E comparable](s1 S, s2 S) bool

Overlaps reports whether s1 and s2 have any element in common.

Time complexity: O(min(len(s1), len(s2))). Space complexity: O(1).

func ProperSubset

func ProperSubset[S1, S2 ~map[E]struct{}, E comparable](subset S1, superset S2) bool

ProperSubset reports whether subset is a proper subset of superset, i.e. all elements of subset are in superset and the sets are not equal.

Time complexity: O(len(subset)). Space complexity: O(1).

func Reduce

func Reduce[S ~map[E]struct{}, E comparable, A any](s S, acc A, f func(A, E) A) A

Reduce returns the result of applying a reduction function f to each element in the input set, accumulating a result starting from the initial value acc. Note: The order of reduction is non-deterministic due to map iteration.

Time complexity: O(len(s)). Space complexity: O(1).

func Replace

func Replace[S ~map[E]struct{}, E comparable](s S, old, new E)

Replace replaces old with new in the set. If old is not present, Replace is a no-op.

Time complexity: O(1). Space complexity: O(1).

func ReplaceFunc

func ReplaceFunc[S ~map[E]struct{}, E comparable](s S, f func(E) E)

ReplaceFunc replaces each element e in s with f(e). Since f may map multiple elements to the same value, the resulting set may be smaller.

Time complexity: O(len(s)). Space complexity: O(1).

Example
package main

import (
	"fmt"

	"github.com/kkhmel/sets"
)

func main() {
	numbers := sets.From(1, 2, 3)
	sets.ReplaceFunc(numbers, func(e int) int { return -e })
	fmt.Println(numbers)

}
Output:

{-1, -2, -3}

func Some

func Some[S ~map[E]struct{}, E comparable](s S, f func(E) bool) bool

Some reports whether at least one element e of s satisfies f(e).

Time complexity: O(len(s)). Space complexity: O(1).

func Subset

func Subset[S1, S2 ~map[E]struct{}, E comparable](subset S1, superset S2) bool

Subset reports whether all elements of subset are also in superset.

Time complexity: O(len(subset)). Space complexity: O(1).

func ToSlice

func ToSlice[S ~map[E]struct{}, E comparable](s S) []E

ToSlice returns all elements of the set as a slice. The order of elements is non-deterministic due to map iteration.

Time complexity: O(len(s)). Space complexity: O(len(s)).

func ToSliceFunc

func ToSliceFunc[S ~map[E]struct{}, E comparable, A any](s S, f func(E) A) []A

ToSliceFunc returns a slice created by applying f to each element of s. The order of elements is non-deterministic due to map iteration.

Time complexity: O(len(s)). Space complexity: O(len(s)).

func UnionSeq

func UnionSeq[S ~map[E]struct{}, E comparable](seq iter.Seq[S]) iter.Seq[E]

UnionSeq returns an iterator over all unique elements from all sets in the sequence. It eliminates duplicates, so each element is yielded only once even if it appears in multiple sets.

Creation: O(1) time, O(1) space. Iteration: O(N) time, O(U) space. N is the total number of elements across all sets. U is the number of unique elements across all sets.

Types

type Pair

type Pair[T, U comparable] struct {
	First  T
	Second U
}

Pair represents an ordered pair of elements, used as the result type for CartesianProduct.

type Set

type Set[E comparable] map[E]struct{}

Set is an implementation of a mathematical set -- a well-defined, unordered collection of distinct objects. Since Set[E] is just a type definition for map[E]struct{}, you can use native Go map operations to work with sets directly. Additionally, all functions from the standard maps package are compatible with sets.

func CartesianProduct

func CartesianProduct[S1 ~map[E1]struct{}, S2 ~map[E2]struct{}, E1, E2 comparable](set1 S1, set2 S2) Set[Pair[E1, E2]]

CartesianProduct returns a new set containing all ordered pairs (e1, e2) where e1 is from set1 and e2 is from set2.

Time complexity: O(len(set1) * len(set2)). Space complexity: O(len(set1) * len(set2)).

func Collect

func Collect[E comparable](seq iter.Seq[E]) Set[E]

Collect collects elements from seq into a new set and returns it.

Time complexity: O(n). Space complexity: O(n). n is the number of seq elements.

func Difference

func Difference[S ~map[E]struct{}, E comparable](minuend S, subtrahends ...S) Set[E]

Difference returns a new set containing elements that are in the minuend but not in any of the subtrahends.

Time complexity: O(len(minuend) + S). Space complexity: O(len(minuend)). S is the sum of subtrahend sizes.

func Filter

func Filter[S ~map[E]struct{}, E comparable](s S, f func(E) bool) Set[E]

Filter returns a new set containing only the elements from the input set that satisfy the predicate function f. The resulting set is pre-allocated with the capacity of the input set for efficiency. Use Clone() on the result if memory optimization is needed.

Time complexity: O(len(s)). Space complexity: O(len(s)).

Example
package main

import (
	"fmt"

	"github.com/kkhmel/sets"
)

func main() {
	numbers := sets.From(1, 2, 3, 4, 5)
	odds := sets.Filter(numbers, func(e int) bool { return e%2 == 1 })
	fmt.Println(odds)

}
Output:

{1, 3, 5}

func From

func From[E comparable](vals ...E) Set[E]

From creates a new Set containing the provided vals. See also FromSlice.

Time complexity: O(len(vals)). Space complexity: O(len(vals)).

func FromSlice

func FromSlice[E comparable](slice []E) Set[E]

FromSlice creates a new Set from an existing slice.

Time complexity: O(len(slice)). Space complexity: O(len(slice)).

Example
package main

import (
	"fmt"

	"github.com/kkhmel/sets"
)

func main() {
	numbers := []int{1, 2, 3, 3, 2, 1}
	s := sets.FromSlice(numbers)
	fmt.Println(s)

}
Output:

{1, 2, 3}

func FromSliceFunc

func FromSliceFunc[A any, E comparable](slice []A, f func(A) E) Set[E]

FromSliceFunc creates a new Set by applying f to each element of the slice.

Time complexity: O(len(slice)). Space complexity: O(len(slice)).

Example
package main

import (
	"fmt"

	"github.com/kkhmel/sets"
)

func main() {
	numbers := []int{1, 2, 3, 3, 2, 1}
	s := sets.FromSliceFunc(numbers, func(e int) int { return -e })
	fmt.Println(s)

}
Output:

{-1, -2, -3}

func Intersection

func Intersection[S ~map[E]struct{}, E comparable](sets ...S) Set[E]

Intersection returns a new set containing only elements that are present in all sets. If no sets are provided, returns an empty set.

Time complexity: O(N). Space complexity: O(min). N is the sum of all set sizes. min is the size of the smallest set.

Example
package main

import (
	"fmt"

	"github.com/kkhmel/sets"
)

func main() {
	set1 := sets.From(1, 2, 3, 4)
	set2 := sets.From(2, 3, 4, 5)
	set3 := sets.From(3, 4, 5, 6)
	intersection := sets.Intersection(set1, set2, set3)
	fmt.Println(intersection)

}
Output:

{3, 4}

func Map

func Map[S ~map[From]struct{}, From, To comparable](s S, f func(From) To) Set[To]

Map returns a new set containing the results of applying a transformation function to each element in the set. The resulting set may have fewer elements than the input set if the function is not injective.

Time complexity: O(len(s)). Space complexity: O(len(s)).

Example
package main

import (
	"fmt"

	"github.com/kkhmel/sets"
)

func main() {
	numbers := sets.From(1, 2, 3)
	doubled := sets.Map(numbers, func(e int) int { return -e })
	fmt.Println(doubled)

}
Output:

{-1, -2, -3}

func New

func New[E comparable](capacity int) Set[E]

New creates a new Set with the specified initial capacity.

Time complexity: O(1). Space complexity: O(n). n is the passed capacity.

func SymmetricDifference

func SymmetricDifference[S ~map[E]struct{}, E comparable](sets ...S) Set[E]

SymmetricDifference returns a new set containing elements that belong to an odd number of the provided sets (i.e., the n-ary XOR of the sets). If no sets are provided, returns an empty set.

Time complexity: O(N). Space complexity: O(N). N is the sum of all set sizes.

func Union

func Union[S ~map[E]struct{}, E comparable](sets ...S) Set[E]

Union returns a new set containing all unique elements from all provided sets. If no sets are provided, returns an empty set.

Time complexity: O(N). Space complexity: O(N). N is the sum of all set sizes.

Example
package main

import (
	"fmt"

	"github.com/kkhmel/sets"
)

func main() {
	set1 := sets.From(1, 2, 3)
	set2 := sets.From(3, 4, 5)
	set3 := sets.From(5, 6, 7)
	union := sets.Union(set1, set2, set3)
	fmt.Println(union)

}
Output:

{1, 2, 3, 4, 5, 6, 7}

func (Set[E]) String

func (s Set[E]) String() string

String returns a string representation of the set in the format "{elem1, elem2, ...}". Elements are sorted by their string representation for consistent output.

Time complexity: O(len(s)). Space complexity: O(len(s)).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL