sets

package
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Aug 7, 2025 License: BSD-3-Clause Imports: 4 Imported by: 0

README

Sets

The sets package provides a generic, thread-safe Set data structure with comprehensive set operations. Built with Go generics, it supports any comparable type and offers both mathematical set operations and functional programming patterns.

Features

  • Generic Implementation: Works with any comparable type (comparable constraint)
  • Rich Set Operations: Union, intersection, difference, symmetric difference
  • Set Relationships: Subset, superset, disjoint, equal checks
  • Functional Helpers: Map-like operations (Any, Every/All, Filter, ForEach)
  • Convenient Constructors: Create sets from slices, other sets, or individual elements
  • Memory Efficient: Uses Go's built-in map with empty struct values

Quick Start

package main

import (
    "fmt"
    "github.com/alextanhongpin/core/types/sets"
)

func main() {
    // Create sets
    numbers := sets.From([]int{1, 2, 3, 4, 5})
    evens := sets.From([]int{2, 4, 6, 8})
    
    // Basic operations
    fmt.Println("Len:", numbers.Len())           // 5
    fmt.Println("Contains 3:", numbers.Has(3))    // true
    
    // Set operations
    intersection := numbers.Intersect(evens)
    fmt.Println("Intersect:", intersection.Slice()) // [2, 4]
    
    union := numbers.Union(evens)
    fmt.Println("Union size:", union.Len())             // 7
}

API Reference

Constructors
// Create empty set
s := sets.New[int]()

// Create from slice
s := sets.From([]string{"a", "b", "c"})

// Create from individual elements  
s := sets.Of("x", "y", "z")
Basic Operations
// Add elements
s.Add("new")
s.Add("a", "b")

// Remove elements
s.Remove("old")
s.Remove("x", "y")

// Check membership
exists := s.Has("item")

// Len and emptiness
size := s.Len()
empty := s.IsEmpty()

// Clear all elements
s.Clear()
Set Operations
a := sets.From([]int{1, 2, 3, 4})
b := sets.From([]int{3, 4, 5, 6})

// Union: {1, 2, 3, 4, 5, 6}
union := a.Union(b)

// Intersect: {3, 4}
intersection := a.Intersect(b)

// Difference: {1, 2}
diff := a.Difference(b)

// Symmetric difference: {1, 2, 5, 6}
symDiff := a.SymmetricDifference(b)
Set Relationships
a := sets.From([]int{1, 2})
b := sets.From([]int{1, 2, 3, 4})
c := sets.From([]int{5, 6})

// Subset checks
fmt.Println(a.IsSubset(b))    // true
fmt.Println(a.IsSuperset(b))  // false

// Disjoint sets (no common elements)
fmt.Println(a.IsDisjoint(c))  // true

// Set equality
fmt.Println(a.Equal(b))       // false
Functional Operations
numbers := sets.From([]int{1, 2, 3, 4, 5})

// Check conditions
hasEven := numbers.Any(func(n int) bool { return n%2 == 0 })
allPositive := numbers.Every(func(n int) bool { return n > 0 })

// Filter elements
evens := numbers.Filter(func(n int) bool { return n%2 == 0 })

// Iterate over elements
numbers.ForEach(func(n int) {
    fmt.Printf("Number: %d\n", n)
})
Conversion and Cloning
s := sets.From([]string{"a", "b", "c"})

// Convert to slice (order not guaranteed)
slice := s.Slice()

// Create independent copy
clone := s.Clone()

Real-World Examples

User Permission System
// Define user roles and permissions
adminPerms := sets.From([]string{"read", "write", "delete", "admin"})
editorPerms := sets.From([]string{"read", "write"})
viewerPerms := sets.From([]string{"read"})

// Check if user can perform action
func canPerform(userPerms, requiredPerms *sets.Set[string]) bool {
    return userPerms.IsSuperset(requiredPerms)
}

// Usage
required := sets.From([]string{"read", "write"})
fmt.Println("Editor can edit:", canPerform(editorPerms, required)) // true
fmt.Println("Viewer can edit:", canPerform(viewerPerms, required)) // false
Tag-Based Content Filtering
// Content with tags
type Content struct {
    ID   string
    Tags *sets.Set[string]
}

articles := []Content{
    {"1", sets.From([]string{"tech", "programming", "go"})},
    {"2", sets.From([]string{"tech", "ai", "machine-learning"})},
    {"3", sets.From([]string{"lifestyle", "health"})},
}

// Filter content by tags
techFilter := sets.From([]string{"tech"})
filtered := make([]Content, 0)

for _, article := range articles {
    if !article.Tags.IsDisjoint(techFilter) {
        filtered = append(filtered, article)
    }
}
// Result: articles 1 and 2
Feature Flag Management
// Feature flags for different environments
prodFeatures := sets.From([]string{"auth", "payments", "analytics"})
stagingFeatures := sets.From([]string{"auth", "payments", "analytics", "debug"})
devFeatures := sets.From([]string{"auth", "payments", "analytics", "debug", "mock-data"})

// Check environment-specific features
func isFeatureEnabled(env string, feature string) bool {
    switch env {
    case "prod":
        return prodFeatures.Has(feature)
    case "staging":
        return stagingFeatures.Has(feature)
    case "dev":
        return devFeatures.Has(feature)
    default:
        return false
    }
}

// Find features only in development
devOnlyFeatures := devFeatures.Difference(prodFeatures)
fmt.Println("Dev-only features:", devOnlyFeatures.Slice()) // ["debug", "mock-data"]
Data Deduplication
// Combine data from multiple sources while avoiding duplicates
source1 := []string{"apple", "banana", "cherry"}
source2 := []string{"banana", "date", "elderberry"}
source3 := []string{"cherry", "fig", "grape"}

// Combine all unique items
combined := sets.New[string]()
combined.Add(source1...)
combined.Add(source2...)
combined.Add(source3...)

uniqueItems := combined.Slice()
fmt.Printf("Unique items: %v\n", uniqueItems)
// Result: All unique fruits from all sources

Performance Characteristics

  • Add/Remove/Contains: O(1) average case
  • Set Operations: O(n) where n is the size of the larger set
  • Memory: O(n) where n is the number of unique elements
  • Thread Safety: Not thread-safe by default (use external synchronization if needed)

Thread Safety

The Set is not thread-safe. For concurrent access, wrap operations with appropriate synchronization:

import "sync"

type SafeSet[T comparable] struct {
    set *sets.Set[T]
    mu  sync.RWMutex
}

func (s *SafeSet[T]) Add(item T) {
    s.mu.Lock()
    defer s.mu.Unlock()
    s.set.Add(item)
}

func (s *SafeSet[T]) Has(item T) bool {
    s.mu.RLock()
    defer s.mu.RUnlock()
    return s.set.Has(item)
}

Best Practices

  1. Use appropriate constructors: From() for slices, Of() for individual elements
  2. Check emptiness: Use IsEmpty() rather than Len() == 0
  3. Immutable operations: Set operations return new sets, leaving originals unchanged
  4. Memory management: Use Clear() to reuse sets rather than creating new ones
  5. Type safety: Leverage Go's type system - all elements must be the same comparable type

Documentation

Overview

Package sets provides a generic Set implementation for any ordered comparable type. Sets are collections of unique elements that support common set operations like union, intersection, difference, and subset testing.

This implementation is optimized for performance and provides a clean API similar to mathematical set operations.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type OrderedComparable

type OrderedComparable interface {
	constraints.Ordered
	comparable
}

OrderedComparable represents types that are both ordered and comparable. This constraint allows sets to be sorted and compared efficiently.

type Set

type Set[T OrderedComparable] struct {
	// contains filtered or unexported fields
}

Set represents a collection of unique elements of type T. The zero value of Set is an empty set ready to use.

Example (AbTesting)

Example: A/B Testing and Experiment Groups

package main

import (
	"fmt"

	"github.com/alextanhongpin/core/types/sets"
)

func main() {
	fmt.Println("A/B Testing Groups:")

	// Define experiment groups
	controlGroup := sets.New("user1", "user3", "user5", "user7", "user9")
	treatmentGroupA := sets.New("user2", "user4", "user6", "user8")
	treatmentGroupB := sets.New("user10", "user11", "user12", "user13")

	// All experiment participants
	allParticipants := controlGroup.Union(treatmentGroupA).Union(treatmentGroupB)
	fmt.Printf("Total participants: %d\n", allParticipants.Len())

	// Ensure no overlap between groups (proper A/B test design)
	controlVsA := controlGroup.IsDisjoint(treatmentGroupA)
	controlVsB := controlGroup.IsDisjoint(treatmentGroupB)
	aVsB := treatmentGroupA.IsDisjoint(treatmentGroupB)

	fmt.Printf("Groups are properly isolated: %v\n", controlVsA && controlVsB && aVsB)

	// Simulate user actions
	purchasedUsers := sets.New("user2", "user4", "user7", "user9", "user11")

	// Calculate conversion rates by group
	controlPurchases := controlGroup.Intersect(purchasedUsers)
	treatmentAPurchases := treatmentGroupA.Intersect(purchasedUsers)
	treatmentBPurchases := treatmentGroupB.Intersect(purchasedUsers)

	fmt.Printf("Control group conversions: %d/%d\n", controlPurchases.Len(), controlGroup.Len())
	fmt.Printf("Treatment A conversions: %d/%d\n", treatmentAPurchases.Len(), treatmentGroupA.Len())
	fmt.Printf("Treatment B conversions: %d/%d\n", treatmentBPurchases.Len(), treatmentGroupB.Len())

}
Output:

A/B Testing Groups:
Total participants: 13
Groups are properly isolated: true
Control group conversions: 2/5
Treatment A conversions: 2/4
Treatment B conversions: 1/4
Example (AccessControl)

Example: Access Control and Security Groups

package main

import (
	"fmt"
	"log"

	"github.com/alextanhongpin/core/types/sets"
)

func main() {
	fmt.Println("Access Control Management:")

	// Define security groups
	adminGroup := sets.New("alice", "bob")
	developersGroup := sets.New("charlie", "diana", "eve")
	qaGroup := sets.New("frank", "grace")
	allEmployees := sets.New("alice", "bob", "charlie", "diana", "eve", "frank", "grace", "henry")

	// Resource access permissions
	sensitiveResourceUsers := adminGroup.Union(sets.New("diana")) // senior developer
	_ = allEmployees                                              // publicResourceUsers for demonstration

	// Check access permissions
	checkAccess := func(user string, resource string, allowedUsers *sets.Set[string]) {
		hasAccess := allowedUsers.Has(user)
		fmt.Printf("User '%s' access to %s: %v\n", user, resource, hasAccess)
	}

	checkAccess("alice", "sensitive resource", sensitiveResourceUsers)
	checkAccess("diana", "sensitive resource", sensitiveResourceUsers)
	checkAccess("charlie", "sensitive resource", sensitiveResourceUsers)

	// Find users without any group membership
	usersInGroups := adminGroup.Union(developersGroup).Union(qaGroup)
	ungroupedUsers := allEmployees.Difference(usersInGroups)
	fmt.Printf("Users without group membership: %s\n", ungroupedUsers)

	// Check if all developers have access to development resources
	devResourceUsers := developersGroup.Union(adminGroup) // admins have dev access too
	allDevsHaveAccess := developersGroup.IsSubset(devResourceUsers)
	fmt.Printf("All developers have dev resource access: %v\n", allDevsHaveAccess)

}

func init() {

	log.SetOutput(nil)
}
Output:

Access Control Management:
User 'alice' access to sensitive resource: true
User 'diana' access to sensitive resource: true
User 'charlie' access to sensitive resource: false
Users without group membership: {henry}
All developers have dev resource access: true
Example (ComplexFiltering)

Example of working with string sets and complex filtering

package main

import (
	"fmt"
	"strings"

	"github.com/alextanhongpin/core/types/sets"
)

func main() {
	fmt.Println("Complex filtering example:")

	// Create a set of words
	words := sets.New("apple", "banana", "cherry", "date", "elderberry", "fig", "grape")

	// Filter words with more than 5 characters
	longWords := words.Filter(func(word string) bool {
		return len(word) > 5
	})
	fmt.Printf("Long words: %s\n", longWords)

	// Check if any word starts with 'a'
	startsWithA := words.Any(func(word string) bool {
		return strings.HasPrefix(word, "a")
	})
	fmt.Printf("Any word starts with 'a': %v\n", startsWithA)

	// Check if all words are lowercase
	allLowercase := words.Every(func(word string) bool {
		return strings.ToLower(word) == word
	})
	fmt.Printf("All words lowercase: %v\n", allLowercase)

	// Count characters in all words
	totalChars := 0
	words.ForEach(func(word string) {
		totalChars += len(word)
	})
	fmt.Printf("Total characters: %d\n", totalChars)

}
Output:

Complex filtering example:
Long words: {banana, cherry, elderberry}
Any word starts with 'a': true
All words lowercase: true
Total characters: 39
Example (ConfigManagement)

Example: Configuration and Environment Management

package main

import (
	"fmt"

	"github.com/alextanhongpin/core/types/sets"
)

func main() {
	fmt.Println("Configuration Management:")

	// Required configurations for different environments
	devConfig := sets.New("debug", "hot-reload", "mock-api", "test-db", "dev-cors")
	stagingConfig := sets.New("logging", "staging-db", "ssl", "monitoring", "backup")
	prodConfig := sets.New("logging", "prod-db", "ssl", "monitoring", "backup", "cdn", "cache")

	// Current environment configuration
	currentConfig := sets.New("debug", "logging", "ssl", "monitoring", "test-db")

	// Check which environment this matches
	fmt.Printf("Current config: %s\n", currentConfig)

	devMatch := currentConfig.Intersect(devConfig).Len()
	stagingMatch := currentConfig.Intersect(stagingConfig).Len()
	prodMatch := currentConfig.Intersect(prodConfig).Len()

	fmt.Printf("Dev environment match: %d/%d configs\n", devMatch, devConfig.Len())
	fmt.Printf("Staging environment match: %d/%d configs\n", stagingMatch, stagingConfig.Len())
	fmt.Printf("Production environment match: %d/%d configs\n", prodMatch, prodConfig.Len())

	// Missing configurations for production
	missingForProd := prodConfig.Difference(currentConfig)
	fmt.Printf("Missing for production: %s\n", missingForProd)

	// Configurations that shouldn't be in production
	invalidForProd := currentConfig.Difference(prodConfig)
	fmt.Printf("Invalid for production: %s\n", invalidForProd)

}
Output:

Configuration Management:
Current config: {debug, logging, monitoring, ssl, test-db}
Dev environment match: 2/5 configs
Staging environment match: 3/5 configs
Production environment match: 3/7 configs
Missing for production: {backup, cache, cdn, prod-db}
Invalid for production: {debug, test-db}
Example (DataDeduplication)

Example: Data Processing and Deduplication

package main

import (
	"fmt"

	"github.com/alextanhongpin/core/types/sets"
)

func main() {
	fmt.Println("Data Deduplication:")

	// Simulate data from different sources
	source1IDs := []int{1, 2, 3, 4, 5, 2, 3} // has duplicates
	source2IDs := []int{3, 4, 5, 6, 7, 8}
	source3IDs := []int{5, 6, 7, 8, 9, 10}

	// Convert to sets (automatically removes duplicates)
	set1 := sets.From(source1IDs)
	set2 := sets.From(source2IDs)
	set3 := sets.From(source3IDs)

	fmt.Printf("Source 1 (deduplicated): %s\n", set1)
	fmt.Printf("Source 2: %s\n", set2)
	fmt.Printf("Source 3: %s\n", set3)

	// All unique IDs across sources
	allUniqueIDs := set1.Union(set2).Union(set3)
	fmt.Printf("All unique IDs: %s\n", allUniqueIDs)

	// IDs present in all sources
	commonIDs := set1.Intersect(set2).Intersect(set3)
	fmt.Printf("IDs in all sources: %s\n", commonIDs)

	// IDs unique to each source
	unique1 := set1.Difference(set2.Union(set3))
	unique2 := set2.Difference(set1.Union(set3))
	unique3 := set3.Difference(set1.Union(set2))

	fmt.Printf("Unique to source 1: %s\n", unique1)
	fmt.Printf("Unique to source 2: %s\n", unique2)
	fmt.Printf("Unique to source 3: %s\n", unique3)

}
Output:

Data Deduplication:
Source 1 (deduplicated): {1, 2, 3, 4, 5}
Source 2: {3, 4, 5, 6, 7, 8}
Source 3: {5, 6, 7, 8, 9, 10}
All unique IDs: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
IDs in all sources: {5}
Unique to source 1: {1, 2}
Unique to source 2: {}
Unique to source 3: {9, 10}
Example (FeatureFlags)

Example: Feature Flag Management

package main

import (
	"fmt"

	"github.com/alextanhongpin/core/types/sets"
)

func main() {
	fmt.Println("Feature Flag Management:")

	// Define feature flags for different environments
	productionFlags := sets.New("feature_a", "feature_b", "feature_stable")
	stagingFlags := sets.New("feature_a", "feature_b", "feature_c", "feature_experimental")
	developmentFlags := sets.New("feature_a", "feature_b", "feature_c", "feature_d", "feature_debug")

	// Features available in all environments
	universalFeatures := productionFlags.Intersect(stagingFlags).Intersect(developmentFlags)
	fmt.Printf("Universal features: %s\n", universalFeatures)

	// Development-only features
	devOnlyFeatures := developmentFlags.Difference(productionFlags)
	fmt.Printf("Development-only features: %s\n", devOnlyFeatures)

	// Features that need production testing
	needsProdTesting := stagingFlags.Difference(productionFlags)
	fmt.Printf("Features needing production testing: %s\n", needsProdTesting)

	// Check if staging is ready for production
	readyForProd := stagingFlags.IsSubset(productionFlags)
	fmt.Printf("Staging ready for production: %v\n", readyForProd)

}
Output:

Feature Flag Management:
Universal features: {feature_a, feature_b}
Development-only features: {feature_c, feature_d, feature_debug}
Features needing production testing: {feature_c, feature_experimental}
Staging ready for production: false
Example (InventoryManagement)

Example: Inventory and Stock Management

package main

import (
	"fmt"

	"github.com/alextanhongpin/core/types/sets"
)

func main() {
	fmt.Println("Inventory Management:")

	// Available products in different warehouses
	warehouse1 := sets.New("laptop", "mouse", "keyboard", "monitor")
	warehouse2 := sets.New("laptop", "printer", "scanner", "keyboard")
	warehouse3 := sets.New("mouse", "monitor", "printer", "webcam")

	// Products available in all warehouses
	universalStock := warehouse1.Intersect(warehouse2).Intersect(warehouse3)
	fmt.Printf("Available in all warehouses: %s\n", universalStock)

	// All unique products across warehouses
	allProducts := warehouse1.Union(warehouse2).Union(warehouse3)
	fmt.Printf("All products: %s\n", allProducts)

	// Products exclusive to each warehouse
	exclusive1 := warehouse1.Difference(warehouse2.Union(warehouse3))
	exclusive2 := warehouse2.Difference(warehouse1.Union(warehouse3))
	exclusive3 := warehouse3.Difference(warehouse1.Union(warehouse2))

	fmt.Printf("Exclusive to warehouse 1: %s\n", exclusive1)
	fmt.Printf("Exclusive to warehouse 2: %s\n", exclusive2)
	fmt.Printf("Exclusive to warehouse 3: %s\n", exclusive3)

	// Customer order checking
	customerOrder := sets.New("laptop", "mouse", "keyboard")

	canFulfillFrom1 := customerOrder.IsSubset(warehouse1)
	canFulfillFrom2 := customerOrder.IsSubset(warehouse2)
	canFulfillFrom3 := customerOrder.IsSubset(warehouse3)

	fmt.Printf("Can fulfill order from warehouse 1: %v\n", canFulfillFrom1)
	fmt.Printf("Can fulfill order from warehouse 2: %v\n", canFulfillFrom2)
	fmt.Printf("Can fulfill order from warehouse 3: %v\n", canFulfillFrom3)

}
Output:

Inventory Management:
Available in all warehouses: {}
All products: {keyboard, laptop, monitor, mouse, printer, scanner, webcam}
Exclusive to warehouse 1: {}
Exclusive to warehouse 2: {scanner}
Exclusive to warehouse 3: {webcam}
Can fulfill order from warehouse 1: true
Can fulfill order from warehouse 2: false
Can fulfill order from warehouse 3: false
Example (SkillsMatching)

Example: Skills Matching for Job Recruitment

package main

import (
	"fmt"

	"github.com/alextanhongpin/core/types/sets"
)

func main() {
	fmt.Println("Skills-based Job Matching:")

	// Job requirements
	backendJobSkills := sets.New("golang", "sql", "docker", "kubernetes", "api-design")
	frontendJobSkills := sets.New("javascript", "react", "css", "html", "typescript")
	fullstackJobSkills := sets.New("golang", "javascript", "react", "sql", "docker")

	// Candidate skills
	candidate1Skills := sets.New("golang", "sql", "docker", "python")
	candidate2Skills := sets.New("javascript", "react", "css", "html", "vue")
	candidate3Skills := sets.New("golang", "javascript", "react", "sql", "docker", "kubernetes")

	// Calculate skill match percentages
	calculateMatch := func(candidateSkills, jobSkills *sets.Set[string]) float64 {
		requiredSkills := jobSkills.Len()
		matchedSkills := candidateSkills.Intersect(jobSkills).Len()
		return float64(matchedSkills) / float64(requiredSkills) * 100
	}

	fmt.Printf("Candidate 1 matches:\n")
	fmt.Printf("  Backend: %.1f%%\n", calculateMatch(candidate1Skills, backendJobSkills))
	fmt.Printf("  Frontend: %.1f%%\n", calculateMatch(candidate1Skills, frontendJobSkills))
	fmt.Printf("  Fullstack: %.1f%%\n", calculateMatch(candidate1Skills, fullstackJobSkills))

	fmt.Printf("Candidate 2 matches:\n")
	fmt.Printf("  Backend: %.1f%%\n", calculateMatch(candidate2Skills, backendJobSkills))
	fmt.Printf("  Frontend: %.1f%%\n", calculateMatch(candidate2Skills, frontendJobSkills))
	fmt.Printf("  Fullstack: %.1f%%\n", calculateMatch(candidate2Skills, fullstackJobSkills))

	fmt.Printf("Candidate 3 matches:\n")
	fmt.Printf("  Backend: %.1f%%\n", calculateMatch(candidate3Skills, backendJobSkills))
	fmt.Printf("  Frontend: %.1f%%\n", calculateMatch(candidate3Skills, frontendJobSkills))
	fmt.Printf("  Fullstack: %.1f%%\n", calculateMatch(candidate3Skills, fullstackJobSkills))

	// Missing skills analysis
	candidate1Missing := backendJobSkills.Difference(candidate1Skills)
	fmt.Printf("Candidate 1 missing skills for backend: %s\n", candidate1Missing)

}
Output:

Skills-based Job Matching:
Candidate 1 matches:
  Backend: 60.0%
  Frontend: 0.0%
  Fullstack: 60.0%
Candidate 2 matches:
  Backend: 0.0%
  Frontend: 80.0%
  Fullstack: 40.0%
Candidate 3 matches:
  Backend: 80.0%
  Frontend: 40.0%
  Fullstack: 100.0%
Candidate 1 missing skills for backend: {api-design, kubernetes}
Example (SocialNetwork)

Example: Social Network Analysis

package main

import (
	"fmt"

	"github.com/alextanhongpin/core/types/sets"
)

func main() {
	fmt.Println("Social Network Analysis:")

	// User connections (followers)
	aliceFollowers := sets.New("bob", "charlie", "diana", "eve")
	bobFollowers := sets.New("alice", "charlie", "frank")
	charlieFollowers := sets.New("alice", "bob", "diana", "grace")
	dianaFollowers := sets.New("alice", "charlie", "eve")

	// Find mutual followers
	aliceBobMutual := aliceFollowers.Intersect(bobFollowers)
	fmt.Printf("Alice & Bob mutual followers: %s\n", aliceBobMutual)

	// Find influencers (users who follow each other)
	aliceCharlieMutual := aliceFollowers.Intersect(charlieFollowers)
	fmt.Printf("Alice & Charlie mutual followers: %s\n", aliceCharlieMutual)

	// Users who follow Alice but not Bob
	aliceExclusive := aliceFollowers.Difference(bobFollowers)
	fmt.Printf("Follow Alice but not Bob: %s\n", aliceExclusive)

	// Total unique users in the network
	allUsers := aliceFollowers.Union(bobFollowers).Union(charlieFollowers).Union(dianaFollowers)
	fmt.Printf("Total unique users: %d - %s\n", allUsers.Len(), allUsers)

	// Find users who are followed by everyone
	followedByAll := aliceFollowers.Intersect(bobFollowers).Intersect(charlieFollowers).Intersect(dianaFollowers)
	fmt.Printf("Followed by everyone: %s\n", followedByAll)

}
Output:

Social Network Analysis:
Alice & Bob mutual followers: {charlie}
Alice & Charlie mutual followers: {bob, diana}
Follow Alice but not Bob: {bob, diana, eve}
Total unique users: 7 - {alice, bob, charlie, diana, eve, frank, grace}
Followed by everyone: {}
Example (TagManagement)

Example: Tag and Category Management

package main

import (
	"fmt"

	"github.com/alextanhongpin/core/types/sets"
)

func main() {
	fmt.Println("Content Tag Management:")

	// Article tags
	article1Tags := sets.New("golang", "programming", "backend", "tutorial")
	article2Tags := sets.New("golang", "web", "frontend", "tutorial")
	article3Tags := sets.New("python", "machine-learning", "data-science")

	// Find articles with common tags
	commonTags := article1Tags.Intersect(article2Tags)
	fmt.Printf("Common tags between article 1 & 2: %s\n", commonTags)

	// All unique tags across articles
	allTags := article1Tags.Union(article2Tags).Union(article3Tags)
	fmt.Printf("All unique tags: %s\n", allTags)

	// Programming-related tags
	programmingTags := sets.New("golang", "python", "programming", "backend", "frontend")

	// Check which articles are programming-related
	fmt.Printf("Article 1 programming-related: %v\n", !article1Tags.IsDisjoint(programmingTags))
	fmt.Printf("Article 2 programming-related: %v\n", !article2Tags.IsDisjoint(programmingTags))
	fmt.Printf("Article 3 programming-related: %v\n", !article3Tags.IsDisjoint(programmingTags))

}
Output:

Content Tag Management:
Common tags between article 1 & 2: {golang, tutorial}
All unique tags: {backend, data-science, frontend, golang, machine-learning, programming, python, tutorial, web}
Article 1 programming-related: true
Article 2 programming-related: true
Article 3 programming-related: true
Example (UserPermissions)

Example: User Permission Management

package main

import (
	"fmt"
	"log"

	"github.com/alextanhongpin/core/types/sets"
)

func main() {
	fmt.Println("User Permission Management:")

	// Define permissions for different roles
	adminPerms := sets.New("read", "write", "delete", "admin", "manage_users")
	editorPerms := sets.New("read", "write", "edit", "publish")
	_ = sets.New("read", "view") // viewerPerms for demonstration

	// User has multiple roles
	userPerms := adminPerms.Union(editorPerms)
	fmt.Printf("User permissions: %s\n", userPerms)

	// Check specific permissions
	canDelete := userPerms.Has("delete")
	canManage := userPerms.Has("manage_users")
	fmt.Printf("Can delete: %v, Can manage users: %v\n", canDelete, canManage)

	// Find common permissions between roles
	commonPerms := adminPerms.Intersect(editorPerms)
	fmt.Printf("Common permissions: %s\n", commonPerms)

	// Admin-only permissions
	adminOnlyPerms := adminPerms.Difference(editorPerms)
	fmt.Printf("Admin-only permissions: %s\n", adminOnlyPerms)

}

func init() {

	log.SetOutput(nil)
}
Output:

User Permission Management:
User permissions: {admin, delete, edit, manage_users, publish, read, write}
Can delete: true, Can manage users: true
Common permissions: {read, write}
Admin-only permissions: {admin, delete, manage_users}

func From

func From[T OrderedComparable](slice []T) *Set[T]

From creates a new set from a slice, removing duplicates.

Example:

slice := []int{1, 2, 3, 2, 1}
s := sets.From(slice) // Set contains {1, 2, 3}

func New

func New[T OrderedComparable](ts ...T) *Set[T]

New creates a new set containing the given elements. Duplicate elements are automatically removed.

Example:

s := sets.New(1, 2, 3, 2, 1) // Set contains {1, 2, 3}

func Of

func Of[T OrderedComparable](ts ...T) *Set[T]

Of is an alias for New, providing a more readable way to create sets.

Example:

s := sets.Of(1, 2, 3) // Set contains {1, 2, 3}

func (*Set[T]) Add

func (s *Set[T]) Add(ts ...T)

Add adds one or more elements to the set. Adding existing elements has no effect.

Example:

s.Add(4, 5, 6)

func (*Set[T]) All

func (s *Set[T]) All() []T

All returns all elements in the set as a sorted slice. The order is guaranteed to be consistent across calls.

Example:

elements := s.All() // []int{1, 2, 3, 4}

func (*Set[T]) Any

func (s *Set[T]) Any(predicate func(T) bool) bool

Any returns true if any element in the set satisfies the predicate.

Example:

s := sets.New(1, 2, 3)
hasEven := s.Any(func(x int) bool { return x%2 == 0 }) // true

func (*Set[T]) Clear

func (s *Set[T]) Clear()

Clear removes all elements from the set.

Example:

s.Clear() // Set becomes empty

func (*Set[T]) Clone

func (s *Set[T]) Clone() *Set[T]

Clone creates a deep copy of the set.

Example:

copy := s.Clone()

func (*Set[T]) Contains

func (s *Set[T]) Contains(t T) bool

Contains is an alias for Has for better readability.

Example:

if s.Contains(42) { /* element exists */ }

func (*Set[T]) Difference

func (s *Set[T]) Difference(other *Set[T]) *Set[T]

Difference returns a new set containing elements in this set but not in the other. The operation is not commutative: A.Difference(B) != B.Difference(A).

Example:

a := sets.New(1, 2, 3)
b := sets.New(2, 3, 4)
c := a.Difference(b) // {1}

func (*Set[T]) Equal

func (s *Set[T]) Equal(other *Set[T]) bool

Equal returns true if both sets contain exactly the same elements.

Example:

a := sets.New(1, 2, 3)
b := sets.New(3, 2, 1)
equal := a.Equal(b) // true

func (*Set[T]) Every

func (s *Set[T]) Every(predicate func(T) bool) bool

Every returns true if all elements in the set satisfy the predicate.

Example:

s := sets.New(2, 4, 6)
allEven := s.Every(func(x int) bool { return x%2 == 0 }) // true

func (*Set[T]) Filter

func (s *Set[T]) Filter(predicate func(T) bool) *Set[T]

Filter returns a new set containing only elements that satisfy the predicate.

Example:

s := sets.New(1, 2, 3, 4, 5)
evens := s.Filter(func(x int) bool { return x%2 == 0 }) // {2, 4}

func (*Set[T]) ForEach

func (s *Set[T]) ForEach(fn func(T))

ForEach iterates over all elements in the set, calling the provided function for each. The iteration order is not guaranteed to be consistent.

Example:

s.ForEach(func(element int) {
    fmt.Println(element)
})

func (*Set[T]) Has

func (s *Set[T]) Has(t T) bool

Has returns true if the set contains the given element.

Example:

if s.Has(42) { /* element exists */ }

func (*Set[T]) Intersect

func (s *Set[T]) Intersect(other *Set[T]) *Set[T]

Intersect returns a new set containing elements that exist in both sets. The operation is commutative: A.Intersect(B) == B.Intersect(A).

Example:

a := sets.New(1, 2, 3)
b := sets.New(2, 3, 4)
c := a.Intersect(b) // {2, 3}

func (*Set[T]) IsDisjoint

func (s *Set[T]) IsDisjoint(other *Set[T]) bool

IsDisjoint returns true if the sets have no elements in common.

Example:

a := sets.New(1, 2)
b := sets.New(3, 4)
isDisjoint := a.IsDisjoint(b) // true

func (*Set[T]) IsEmpty

func (s *Set[T]) IsEmpty() bool

IsEmpty returns true if the set contains no elements.

Example:

if s.IsEmpty() { /* handle empty set */ }

func (*Set[T]) IsProperSubset

func (s *Set[T]) IsProperSubset(other *Set[T]) bool

IsProperSubset returns true if this set is a subset of the other but not equal to it.

Example:

a := sets.New(1, 2)
b := sets.New(1, 2, 3)
isProperSubset := a.IsProperSubset(b) // true

func (*Set[T]) IsProperSuperset

func (s *Set[T]) IsProperSuperset(other *Set[T]) bool

IsProperSuperset returns true if this set is a superset of the other but not equal to it.

Example:

a := sets.New(1, 2, 3)
b := sets.New(1, 2)
isProperSuperset := a.IsProperSuperset(b) // true

func (*Set[T]) IsSubset

func (s *Set[T]) IsSubset(other *Set[T]) bool

IsSubset returns true if all elements of this set are contained in the other set.

Example:

a := sets.New(1, 2)
b := sets.New(1, 2, 3)
isSubset := a.IsSubset(b) // true

func (*Set[T]) IsSuperset

func (s *Set[T]) IsSuperset(other *Set[T]) bool

IsSuperset returns true if this set contains all elements of the other set.

Example:

a := sets.New(1, 2, 3)
b := sets.New(1, 2)
isSuperset := a.IsSuperset(b) // true

func (*Set[T]) Len

func (s *Set[T]) Len() int

Len returns the number of elements in the set.

Example:

count := s.Len()

func (*Set[T]) Remove

func (s *Set[T]) Remove(ts ...T)

Remove removes one or more elements from the set. Removing non-existent elements has no effect.

Example:

s.Remove(1, 2)

func (*Set[T]) Slice

func (s *Set[T]) Slice() []T

Slice is an alias for All for better API consistency.

Example:

slice := s.Slice()

func (*Set[T]) String

func (s *Set[T]) String() string

String returns a string representation of the set.

Example:

fmt.Printf("Set: %s\n", s) // Set: {1, 2, 3}

func (*Set[T]) SymmetricDifference

func (s *Set[T]) SymmetricDifference(other *Set[T]) *Set[T]

SymmetricDifference returns a new set containing elements in either set but not in both. The operation is commutative: A.SymmetricDifference(B) == B.SymmetricDifference(A).

Example:

a := sets.New(1, 2, 3)
b := sets.New(2, 3, 4)
c := a.SymmetricDifference(b) // {1, 4}

func (*Set[T]) Union

func (s *Set[T]) Union(other *Set[T]) *Set[T]

Union returns a new set containing all elements from both sets. The operation is commutative: A.Union(B) == B.Union(A).

Example:

a := sets.New(1, 2, 3)
b := sets.New(2, 3, 4)
c := a.Union(b) // {1, 2, 3, 4}

Jump to

Keyboard shortcuts

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