gods/sparsex/main.go

167 lines
3.2 KiB
Go

package sparsex
import (
"sort"
cons "golang.org/x/exp/constraints"
)
// The package implements sparse array structure.
// You can make sparse matrices by assigning
// the value type to another sparse array.
// The sparse array type.
// Does not sort by default on setting so by
// default is not ordered for the Chan, Keys, KeyChan, Slice methods.
// Its made for the optimization sakes because
// initially the package was made for the gox (2D game engine) package use
// to provide dynamic layering.
// See *Sparse[K, V].ShouldSort method to change it.
type Sparse[K cons.Ordered, V any] struct {
store map[K] V
def V
keys []K
shouldSort bool
}
// Returns new sparse array taking all the values from valuesStores
// into the structure.
func New[K cons.Ordered, V any](valueStores ...map[K] V) *Sparse[K, V] {
finalLen := 0
for _, valueStore := range valueStores {
finalLen = len(valueStore)
}
keys := make([]K, finalLen)
store := make(map[K] V)
for _, valueStore := range valueStores {
i := 0
for k, v := range valueStore {
keys[i] = k
store[k] = v
i++
}
}
return &Sparse[K, V]{
store: store,
keys: keys,
}
}
// Define if should sort each time we set or delete.
func (s *Sparse[K, V]) ShouldSort(v bool) *Sparse[K, V] {
s.shouldSort = v
if s.shouldSort {
s.Sort()
}
return s
}
// Sets the default sparse array value.
// Returned when there is no key for the value.
func (s *Sparse[K, V]) Default(v V) *Sparse[K, V] {
s.def = v
return s
}
// Get the value by the key. The secound value
// represents whether the array contains the value.
// If the array does not contain the value then default one
// will be returned.
func (s *Sparse[K, V]) Get(key K) (V, bool) {
val, ok := s.store[key]
if !ok {
val = s.def
}
return val, ok
}
// Set the value to the key.
func (s *Sparse[K, V]) Set(k K, v V) {
_, ok := s.store[k]
if !ok {
s.keys = append(s.keys, k)
if s.shouldSort {
s.Sort()
}
}
s.store[k] = v
}
// Delete the value by the key.
func (s *Sparse[K, V]) Delete(k K) {
delete(s.store, k)
// To know if the loop was run.
idx := -1
for i, v := range s.keys {
if v == k {
idx = i
break
}
}
if idx != -1 {
s.keys = append(s.keys[:idx], s.keys[idx+1:]...)
if s.shouldSort {
s.Sort()
}
}
}
// Alias for the Delete method.
func (s *Sparse[K, V]) Del(k K) {
s.Delete(k)
}
// Returns channel of pairs.
func (s *Sparse[K, V]) Chan(
) chan V {
keys := s.keys
store := s.store
ret := make(chan V)
go func() {
for _, k := range keys {
ret <- store[k]
}
close(ret)
}()
return ret
}
// Returns a slice of the keys of the array.
func (s *Sparse[K, V]) Keys() []K {
return s.keys
}
// Returns channel of keys in its order in the structure.
func (s *Sparse[K, V]) KeyChan() chan K {
ret := make(chan K)
go func() {
for _, k := range s.keys {
ret <- k
}
close(ret)
}()
return ret
}
// Returns slice of the already set values.
func (s *Sparse[K, V]) Slice() []V {
ret := []V{}
for v := range s.Chan() {
ret = append(ret, v)
}
return ret
}
// Sort the keys making current array finely ordered.
func (s *Sparse[K, V]) Sort() {
sort.Slice(s.keys, func(i, j int) bool {
return s.keys[i] < s.keys[j]
})
}