mirror of
https://github.com/luxfi/container.git
synced 2026-09-24 00:24:34 +00:00
138 lines
3.1 KiB
Go
138 lines
3.1 KiB
Go
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package setmap
|
|
|
|
import (
|
|
"github.com/luxfi/math/set"
|
|
)
|
|
|
|
type Entry[K any, V comparable] struct {
|
|
Key K
|
|
Set set.Set[V]
|
|
}
|
|
|
|
// SetMap is a map to a set where all sets are non-overlapping.
|
|
type SetMap[K, V comparable] struct {
|
|
keyToSet map[K]set.Set[V]
|
|
valueToKey map[V]K
|
|
}
|
|
|
|
// New creates a new empty setmap.
|
|
func New[K, V comparable]() *SetMap[K, V] {
|
|
return &SetMap[K, V]{
|
|
keyToSet: make(map[K]set.Set[V]),
|
|
valueToKey: make(map[V]K),
|
|
}
|
|
}
|
|
|
|
// Put the new entry into the map. Removes and returns:
|
|
// * The existing entry for [key].
|
|
// * Existing entries where the set overlaps with the [set].
|
|
func (m *SetMap[K, V]) Put(key K, set set.Set[V]) []Entry[K, V] {
|
|
removed := m.DeleteOverlapping(set)
|
|
if removedSet, ok := m.DeleteKey(key); ok {
|
|
removed = append(removed, Entry[K, V]{
|
|
Key: key,
|
|
Set: removedSet,
|
|
})
|
|
}
|
|
|
|
m.keyToSet[key] = set
|
|
for val := range set {
|
|
m.valueToKey[val] = key
|
|
}
|
|
return removed
|
|
}
|
|
|
|
// GetKey that maps to the provided value.
|
|
func (m *SetMap[K, V]) GetKey(val V) (K, bool) {
|
|
key, ok := m.valueToKey[val]
|
|
return key, ok
|
|
}
|
|
|
|
// GetSet that is mapped to by the provided key.
|
|
func (m *SetMap[K, V]) GetSet(key K) (set.Set[V], bool) {
|
|
val, ok := m.keyToSet[key]
|
|
return val, ok
|
|
}
|
|
|
|
// HasKey returns true if [key] is in the map.
|
|
func (m *SetMap[K, _]) HasKey(key K) bool {
|
|
_, ok := m.keyToSet[key]
|
|
return ok
|
|
}
|
|
|
|
// HasValue returns true if [val] is in a set in the map.
|
|
func (m *SetMap[_, V]) HasValue(val V) bool {
|
|
_, ok := m.valueToKey[val]
|
|
return ok
|
|
}
|
|
|
|
// HasOverlap returns true if [set] overlaps with any of the sets in the map.
|
|
func (m *SetMap[_, V]) HasOverlap(set set.Set[V]) bool {
|
|
if set.Len() < len(m.valueToKey) {
|
|
for val := range set {
|
|
if _, ok := m.valueToKey[val]; ok {
|
|
return true
|
|
}
|
|
}
|
|
} else {
|
|
for val := range m.valueToKey {
|
|
if set.Contains(val) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// DeleteKey removes [key] from the map and returns the set it mapped to.
|
|
func (m *SetMap[K, V]) DeleteKey(key K) (set.Set[V], bool) {
|
|
set, ok := m.keyToSet[key]
|
|
if !ok {
|
|
return nil, false
|
|
}
|
|
|
|
delete(m.keyToSet, key)
|
|
for val := range set {
|
|
delete(m.valueToKey, val)
|
|
}
|
|
return set, true
|
|
}
|
|
|
|
// DeleteValue removes and returns the entry that contained [val].
|
|
func (m *SetMap[K, V]) DeleteValue(val V) (K, set.Set[V], bool) {
|
|
key, ok := m.valueToKey[val]
|
|
if !ok {
|
|
return zero[K](), nil, false
|
|
}
|
|
set, _ := m.DeleteKey(key)
|
|
return key, set, true
|
|
}
|
|
|
|
// DeleteOverlapping removes and returns all the entries where the set overlaps
|
|
// with [set].
|
|
func (m *SetMap[K, V]) DeleteOverlapping(set set.Set[V]) []Entry[K, V] {
|
|
var removed []Entry[K, V]
|
|
for val := range set {
|
|
if k, removedSet, ok := m.DeleteValue(val); ok {
|
|
removed = append(removed, Entry[K, V]{
|
|
Key: k,
|
|
Set: removedSet,
|
|
})
|
|
}
|
|
}
|
|
return removed
|
|
}
|
|
|
|
// Len return the number of sets in the map.
|
|
func (m *SetMap[K, V]) Len() int {
|
|
return len(m.keyToSet)
|
|
}
|
|
|
|
// LenValues return the total number of values across all sets in the map.
|
|
func (m *SetMap[K, V]) LenValues() int {
|
|
return len(m.valueToKey)
|
|
}
|