188 lines
3.4 KiB
Go
188 lines
3.4 KiB
Go
package dataext
|
|
|
|
import (
|
|
"fmt"
|
|
"iter"
|
|
)
|
|
|
|
// OrderedMap is like a normal map[TKey, TVal] - but its elements stay in order
|
|
// NOT THREADSAFE !!!
|
|
type OrderedMap[TKey comparable, TVal any] struct {
|
|
m map[TKey]*TVal
|
|
a []TKey
|
|
}
|
|
|
|
func NewOrderedMap[TKey comparable, TVal any](caps ...int) *OrderedMap[TKey, TVal] {
|
|
if len(caps) == 0 {
|
|
return &OrderedMap[TKey, TVal]{
|
|
m: make(map[TKey]*TVal),
|
|
a: make([]TKey, 0),
|
|
}
|
|
}
|
|
|
|
omcap := 0
|
|
for _, v := range caps {
|
|
omcap += v
|
|
}
|
|
|
|
return &OrderedMap[TKey, TVal]{
|
|
m: make(map[TKey]*TVal, omcap),
|
|
a: make([]TKey, 0, omcap),
|
|
}
|
|
}
|
|
|
|
func (o *OrderedMap[TKey, TVal]) Get(key TKey) (TVal, bool) {
|
|
v, ok := o.m[key]
|
|
if ok {
|
|
return *v, ok
|
|
}
|
|
|
|
return *new(TVal), false
|
|
}
|
|
|
|
func (o *OrderedMap[TKey, TVal]) GetOrNil(key TKey) *TVal {
|
|
v, ok := o.m[key]
|
|
if ok {
|
|
return v
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (o *OrderedMap[TKey, TVal]) GetOrDefault(key TKey, defaultVal TVal) TVal {
|
|
v, ok := o.m[key]
|
|
if ok {
|
|
return *v
|
|
}
|
|
|
|
return defaultVal
|
|
}
|
|
|
|
// Add adds the new value to the map
|
|
// At the end of the map-ordering (even if key already exists, its then "moved" to the end)
|
|
// returns true if key already existed
|
|
func (o *OrderedMap[TKey, TVal]) Add(key TKey, val TVal) bool {
|
|
if _, ok := o.m[key]; ok {
|
|
o.remFromArray(key)
|
|
o.m[key] = &val
|
|
o.a = append(o.a, key)
|
|
return true
|
|
}
|
|
|
|
o.m[key] = &val
|
|
o.a = append(o.a, key)
|
|
return false
|
|
}
|
|
|
|
// AddOrReplace adds the new value to the map
|
|
// Normally at the end of the map, but if teh key already exists, its only replaced
|
|
// returns true if key already existed
|
|
func (o *OrderedMap[TKey, TVal]) AddOrReplace(key TKey, val TVal) bool {
|
|
if _, ok := o.m[key]; ok {
|
|
o.m[key] = &val
|
|
return true
|
|
}
|
|
|
|
o.m[key] = &val
|
|
o.a = append(o.a, key)
|
|
return false
|
|
}
|
|
|
|
func (o *OrderedMap[TKey, TVal]) Remove(key TKey) bool {
|
|
if _, ok := o.m[key]; ok {
|
|
o.remFromArray(key)
|
|
delete(o.m, key)
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (o *OrderedMap[TKey, TVal]) Iterate() iter.Seq2[TKey, TVal] {
|
|
return func(yield func(TKey, TVal) bool) {
|
|
for _, v := range o.a {
|
|
if !yield(v, *o.m[v]) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (o *OrderedMap[TKey, TVal]) IterateValues() iter.Seq[TVal] {
|
|
return func(yield func(TVal) bool) {
|
|
for _, v := range o.a {
|
|
if !yield(*o.m[v]) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (o *OrderedMap[TKey, TVal]) IterateKeys() iter.Seq[TKey] {
|
|
return func(yield func(TKey) bool) {
|
|
for _, v := range o.a {
|
|
if !yield(v) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (o *OrderedMap[TKey, TVal]) Array() []TVal {
|
|
res := make([]TVal, len(o.a))
|
|
for i, v := range o.a {
|
|
res[i] = *o.m[v]
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
func (o *OrderedMap[TKey, TVal]) Keys() []TKey {
|
|
res := make([]TKey, len(o.a))
|
|
for i, v := range o.a {
|
|
res[i] = v
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
func (o *OrderedMap[TKey, TVal]) Clear() {
|
|
mapCap := max(len(o.m), cap(o.a))
|
|
o.m = make(map[TKey]*TVal, mapCap)
|
|
o.a = make([]TKey, 0, mapCap)
|
|
}
|
|
|
|
func (o *OrderedMap[TKey, TVal]) Size() int {
|
|
return len(o.a)
|
|
}
|
|
|
|
func (o *OrderedMap[TKey, TVal]) Capacity() int {
|
|
return min(cap(o.a), len(o.m))
|
|
}
|
|
|
|
func (o *OrderedMap[TKey, TVal]) Contains(key TKey) bool {
|
|
_, ok := o.m[key]
|
|
return ok
|
|
}
|
|
|
|
func (o *OrderedMap[TKey, TVal]) IndexOf(key TKey) int {
|
|
for i, v := range o.a {
|
|
if v == key {
|
|
return i
|
|
}
|
|
}
|
|
|
|
return -1
|
|
}
|
|
|
|
func (o *OrderedMap[TKey, TVal]) remFromArray(key TKey) {
|
|
for i, v := range o.a {
|
|
if v == key {
|
|
o.a = append(o.a[:i], o.a[i+1:]...)
|
|
return
|
|
}
|
|
}
|
|
|
|
panic(fmt.Sprintf("Failed to remove key from OrderedMap -- key '%v' not found", key))
|
|
}
|