//nolint:revive package set import ( "maps" "slices" ) type Set[K comparable] map[K]void type void struct{} var member = void{} func New[K comparable]() Set[K] { return Set[K]{} } // Creates a set from each item in a slice. func FromSlice[S ~[]K, K comparable](slice S) Set[K] { set := New[K]() set.Add(slice...) return set } // Creates a set from each key in a map. func FromMap[M ~map[K]V, K comparable, V any](m M) Set[K] { return FromSlice(mapKeys(m)) } // Returns a slice of the members in a set. func (set Set[K]) ToSlice() []K { return mapKeys(set) } // Adds members to the set. func (set Set[K]) Add(items ...K) { for _, item := range items { set[item] = member } } // Removes members from the set, if they exists. func (set Set[K]) Remove(items ...K) { for _, item := range items { delete(set, item) } } // Returns true if the set has a given member. func (set Set[K]) HasMember(item K) bool { _, ok := set[item] return ok } // A u B, i.e. all members of A and B. func (left Set[K]) Union(right Set[K]) Set[K] { union := Set[K]{} for item := range left { union.Add(item) } for item := range right { union.Add(item) } return union } // A n B, i.e. the members in both A and B. func (left Set[K]) Intersection(right Set[K]) Set[K] { intersection := Set[K]{} for item := range left { if right.HasMember(item) { intersection.Add(item) } } return intersection } // A - B, i.e. the members of A without any members also in B. func (left Set[K]) Difference(right Set[K]) Set[K] { difference := left for item := range right { difference.Remove(item) } return difference } // (A u B) - (A n B), i.e. the members of A and B, but not in both. func (left Set[K]) SymmetricDifference(right Set[K]) Set[K] { return left.Union(right).Difference(left.Intersection(right)) } func mapKeys[M ~map[K]V, K comparable, V any](m M) []K { return slices.Collect(maps.Keys(m)) }