slices

package
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Jul 27, 2025 License: MIT Imports: 3 Imported by: 0

README

darvaza.org/x/container/slices

The slices package provides a higher-level abstraction and functionality based on the standard Go slices.

Set[T]

Set[T] is a generic interface that represents a set of values implemented over a slice.

CustomSet[T] is a generic type that implements the Set[T] interface using a sorted slice underneath. A comparison function is required to be provided at initialization time via NewCustomSet[T]() or MustCustomSet[T]() and the initial values can optionally be included as extra arguments.

NewOrderedSet[T]() is a convenience factory using a default comparison function for ordered generic types.

For use with embedded CustomSet[T] variables, InitCustomSet[T] and InitOrderedSet[T] are available.

CustomSet[T] additions

For performance, CustomSet[T] implements two methods not covered by the Set[T] interface.

  • Clone() Set[T] to create a copy with the same elements and comparison function.
  • and New() to create a new empty set with the same comparison function.

See also

Documentation

Overview

Package slices provides generic slices utilities.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func InitCustomSet

func InitCustomSet[T any](set *CustomSet[T], cmp func(T, T) int, initial ...T) error

InitCustomSet initializes a pre-allocated CustomSet with thread-safe semantics. Returns an error if the set is nil, the comparison function is nil, or the set is already initialized.

func InitOrderedSet

func InitOrderedSet[T core.Ordered](set *CustomSet[T], initial ...T) error

InitOrderedSet initializes a CustomSet with a default comparison function for ordered types. It sets the comparison function and populates the set with the initial elements. Returns an error if the initialization fails.

Types

type CustomSet

type CustomSet[T any] struct {
	// contains filtered or unexported fields
}

CustomSet is a generic thread-safe set implementation with custom element comparison. It maintains a sorted slice of unique elements using a provided comparison function.

func MustCustomSet

func MustCustomSet[T any](cmd func(T, T) int, initial ...T) *CustomSet[T]

MustCustomSet creates a new CustomSet, panicking if initialization fails. This is a convenience function for when error handling is not needed.

func NewCustomSet

func NewCustomSet[T any](cmp func(T, T) int, initial ...T) (*CustomSet[T], error)

NewCustomSet creates a new CustomSet with the provided comparison function and initial elements. The comparison function should return negative if a<b, zero if a==b, and positive if a>b. Returns an error if the comparison function is nil.

Example
package main

import (
	"fmt"

	"darvaza.org/x/container/slices"
)

func main() {
	// Custom type with comparison function
	type Person struct {
		ID   int
		Name string
	}

	// Compare by ID
	cmpByID := func(a, b Person) int {
		if a.ID < b.ID {
			return -1
		}
		if a.ID > b.ID {
			return 1
		}
		return 0
	}

	// Create set with custom comparison
	set, err := slices.NewCustomSet(cmpByID,
		Person{ID: 3, Name: "Charlie"},
		Person{ID: 1, Name: "Alice"},
		Person{ID: 2, Name: "Bob"},
		Person{ID: 1, Name: "Alice Duplicate"}, // Will be ignored
	)
	if err != nil {
		panic(err)
	}

	fmt.Println("People count:", set.Len())

	// Export in sorted order (by ID)
	people := set.Export()
	for _, p := range people {
		fmt.Printf("ID=%d: %s\n", p.ID, p.Name)
	}

}
Output:

People count: 3
ID=1: Alice
ID=2: Bob
ID=3: Charlie

func NewOrderedSet

func NewOrderedSet[T core.Ordered](initial ...T) *CustomSet[T]

NewOrderedSet creates a new CustomSet with a default comparison function for ordered types.

Example
package main

import (
	"fmt"

	"darvaza.org/x/container/slices"
)

func main() {
	// Create a set of integers
	set := slices.NewOrderedSet(3, 1, 4, 1, 5, 9, 2, 6)

	// The set automatically deduplicates and sorts
	fmt.Println("Length:", set.Len())
	fmt.Println("Contains 4:", set.Contains(4))
	fmt.Println("Contains 7:", set.Contains(7))

	// Export returns a sorted slice
	values := set.Export()
	fmt.Println("Values:", values)

}
Output:

Length: 7
Contains 4: true
Contains 7: false
Values: [1 2 3 4 5 6 9]

func (*CustomSet[T]) Add

func (set *CustomSet[T]) Add(values ...T) int

Add adds the given values to the CustomSet. Returns the number of unique values that were added. Panics if the set is not properly initialized.

Example
package main

import (
	"fmt"

	"darvaza.org/x/container/slices"
)

func main() {
	set := slices.NewOrderedSet[int]()

	// Add single value
	added := set.Add(5)
	fmt.Println("Added 5:", added)

	// Add multiple values
	added = set.Add(3, 7, 1, 9)
	fmt.Println("Added 4 values:", added)

	// Try to add duplicates
	added = set.Add(5, 3, 11)
	fmt.Println("Added with duplicates:", added)

	fmt.Println("Final set:", set.Export())

}
Output:

Added 5: 1
Added 4 values: 4
Added with duplicates: 1
Final set: [1 3 5 7 9 11]

func (*CustomSet[T]) Cap

func (set *CustomSet[T]) Cap() (available, total int)

Cap returns the available and total capacity of the CustomSet. The first return value is available capacity, and the second is total capacity. Returns (0, 0) if the set is nil.

func (*CustomSet[T]) Clear

func (set *CustomSet[T]) Clear()

Clear removes all elements from the set, resetting it to an empty state. Does nothing if the set is nil.

func (*CustomSet[T]) Clone added in v0.2.5

func (set *CustomSet[T]) Clone() Set[T]

Clone creates a copy of the CustomSet. Returns nil if the current set is nil, and panics if not initialized.

Example
package main

import (
	"fmt"

	"darvaza.org/x/container/slices"
)

func main() {
	original := slices.NewOrderedSet(1, 2, 3)

	// Create a clone
	clone := original.Clone()

	// Modify original
	original.Add(4)

	// Clone is independent
	fmt.Println("Original:", original.Export())
	fmt.Println("Clone:", clone.Export())

}
Output:

Original: [1 2 3 4]
Clone: [1 2 3]

func (*CustomSet[T]) Contains

func (set *CustomSet[T]) Contains(v T) bool

Contains checks if the given value is present in the CustomSet. Returns false if the set is nil or not initialized.

func (*CustomSet[T]) Export

func (set *CustomSet[T]) Export() []T

Export returns a copy of the set's elements as a new slice. Returns nil if the set is nil.

func (*CustomSet[T]) ForEach

func (set *CustomSet[T]) ForEach(fn func(T) bool)

ForEach iterates over each element in the set, applying the provided function. Stops iteration if the function returns false. Does nothing if either the set or function is nil.

Example
package main

import (
	"fmt"

	"darvaza.org/x/container/slices"
)

func main() {
	set := slices.NewOrderedSet(10, 20, 30, 40, 50)

	// Sum all values
	sum := 0
	set.ForEach(func(v int) bool {
		sum += v
		return true // continue
	})
	fmt.Println("Sum:", sum)

	// Find first value > 25
	var found int
	set.ForEach(func(v int) bool {
		if v > 25 {
			found = v
			return false // stop
		}
		return true
	})
	fmt.Println("First > 25:", found)

}
Output:

Sum: 150
First > 25: 30

func (*CustomSet[T]) GetByIndex

func (set *CustomSet[T]) GetByIndex(i int) (T, bool)

GetByIndex returns the element at the specified index in the set. If the index is out of bounds, it returns the zero value and false. This is concurrency-safe but it's only intended to be used when testing, always prefer ForEach() or Export() instead.

func (*CustomSet[T]) Grow

func (set *CustomSet[T]) Grow(additional int) bool

Grow increases the capacity of the set by the specified additional amount. Returns true if the capacity was increased, false otherwise.

func (*CustomSet[T]) Len

func (set *CustomSet[T]) Len() int

Len returns the number of elements in the CustomSet. Returns 0 if the set is nil.

func (*CustomSet[T]) New added in v0.2.5

func (set *CustomSet[T]) New() Set[T]

New creates a new empty CustomSet with the same comparison function as the current set. Returns nil if the current set is nil, and panics if the set is not initialized.

func (*CustomSet[T]) Purge added in v0.2.4

func (set *CustomSet[T]) Purge() []T

Purge removes and returns all elements from the set. Unlike Clear(), this transfers ownership of the underlying slice to the caller. Returns nil if the set is nil.

func (*CustomSet[T]) Remove

func (set *CustomSet[T]) Remove(values ...T) int

Remove removes the given values from the CustomSet. Returns the number of values that were actually removed. Panics if the set is not properly initialized.

Example
package main

import (
	"fmt"

	"darvaza.org/x/container/slices"
)

func main() {
	set := slices.NewOrderedSet(1, 2, 3, 4, 5)

	// Remove existing value
	removed := set.Remove(3)
	fmt.Println("Removed 3:", removed)

	// Remove non-existing value
	removed = set.Remove(10)
	fmt.Println("Removed 10:", removed)

	// Remove multiple values
	removed = set.Remove(1, 5)
	fmt.Println("Removed 1 and 5:", removed)

	fmt.Println("Remaining:", set.Export())

}
Output:

Removed 3: 1
Removed 10: 0
Removed 1 and 5: 2
Remaining: [2 4]

func (*CustomSet[T]) Reserve

func (set *CustomSet[T]) Reserve(capacity int) bool

Reserve increases the capacity of the set to at least the specified capacity. Returns true if the capacity was increased, false if the set is nil or already has sufficient capacity.

Example
package main

import (
	"fmt"

	"darvaza.org/x/container/slices"
)

func main() {
	set := slices.NewOrderedSet[int]()

	// Reserve capacity for 100 elements
	reserved := set.Reserve(100)
	fmt.Println("Reserved for 100:", reserved)

	available, total := set.Cap()
	fmt.Printf("Capacity: %d available, %d total\n", available, total)

	// Add some elements
	set.Add(1, 2, 3, 4, 5)

	// Trim excess capacity
	trimmed := set.Trim()
	fmt.Println("Trimmed:", trimmed)

	available, total = set.Cap()
	fmt.Printf("After trim: %d available, %d total\n", available, total)

}
Output:

Reserved for 100: true
Capacity: 100 available, 100 total
Trimmed: true
After trim: 0 available, 5 total

func (*CustomSet[T]) Trim

func (set *CustomSet[T]) Trim() bool

Trim reduces the capacity of the set to match its length. Returns true if the capacity was reduced, false otherwise.

func (*CustomSet[T]) TrimN

func (set *CustomSet[T]) TrimN(minCapacity int) bool

TrimN reduces the capacity of the set while maintaining at least the specified minimum capacity. Returns true if the capacity was reduced, false otherwise.

type Set

type Set[T any] interface {
	// Contains reports whether the set contains the given value v.
	Contains(v T) bool
	// Len returns the number of elements currently in the set.
	Len() int
	// Cap returns the available and current capacity of the underlying slice.
	Cap() (available, total int)

	// Add adds one or more elements to the set and returns the number of elements successfully added.
	// Elements that already exist in the set are not added and do not contribute to the return value.
	Add(...T) int
	// Remove removes one or more elements from the set and returns the number of elements successfully removed.
	// Elements that do not exist in the set are ignored and do not contribute to the return value.
	Remove(...T) int

	// Clear removes all elements from the set, leaving it empty. Total capacity remains.
	Clear()

	// Purge removes all elements from the set, leaving it with zero capacity. It returns the elements
	// the Set contained.
	Purge() []T

	// Export returns a copy of the elements currently in the set as a new slice.
	// The order of elements in the returned slice is not necessarily the same as the order in which
	// they were added.
	Export() []T
	// ForEach applies the provided function to each element in the set, stopping if the function returns false.
	// The function is passed the element as an argument and should return true to continue iterating, or false to stop.
	ForEach(func(T) bool)

	// Reserve attempts to increase the underlying slice's capacity to accommodate the
	// specified number of additional elements.
	// It returns true if the capacity was increased, or otherwise false.
	Reserve(capacity int) bool
	// Grow increases the capacity of the underlying slice to accommodate the specified number of additional elements.
	// It returns true if the capacity was increased, or otherwise false.
	Grow(additional int) bool
	// Trim reduces the capacity of the underlying slice to match its length, potentially freeing unused memory.
	// It returns true if the capacity was effectively reduced, or false otherwise.
	Trim() bool
	// TrimN reduces the capacity of the underlying slice to match its length, optionally ensuring a minimum capacity.
	// It returns true if the capacity was effectively reduced, or false otherwise.
	TrimN(minimumCapacity int) bool
}

Set is a generic interface for a mutable set of elements with dynamic capacity management. It provides methods for adding, removing, checking, and manipulating a collection of unique elements. The type parameter T allows the set to work with any type that supports comparison.

Jump to

Keyboard shortcuts

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