From c362c45038d4089d43d76754eb721eda68982867 Mon Sep 17 00:00:00 2001 From: surdeus Date: Mon, 28 Aug 2023 12:06:51 +0300 Subject: [PATCH] Fixed some sparsex issues. --- cmd/sparse/main.go | 20 +++++++++ sparsex/main.go | 108 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 109 insertions(+), 19 deletions(-) create mode 100644 cmd/sparse/main.go diff --git a/cmd/sparse/main.go b/cmd/sparse/main.go new file mode 100644 index 0000000..a47b8a4 --- /dev/null +++ b/cmd/sparse/main.go @@ -0,0 +1,20 @@ +package main + +import ( + "github.com/mojosa-software/godat/sparsex" + "fmt" +) + +func main() { + arr := sparsex.New[float64, string](map[float64] string { + 5: "something at 5", + 12: "new shit", + 50: "die", + }). + Default("") + + arr.Del(12) + for v := range arr.Chan() { + fmt.Println(v) + } +} diff --git a/sparsex/main.go b/sparsex/main.go index 538a914..e2a8055 100644 --- a/sparsex/main.go +++ b/sparsex/main.go @@ -3,33 +3,75 @@ package sparsex import ( "sort" cons "golang.org/x/exp/constraints" - "github.com/mojosa-software/godat/src/iterx" ) -// The package implements a simple ordered map. -// In fact can be used as a sparse array so it is -// where the name comes from. +// 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. -// If shouldSort == true then it will sort the array on -// each change. -func New[K cons.Ordered, V any]() *Sparse[K, V] { +// 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: make(map[K] V), - keys: []K{}, + store: store, + keys: keys, } } -// Get the value by the key. +// 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 } @@ -47,7 +89,7 @@ func (s *Sparse[K, V]) Set(k K, v V) { } // Delete the value by the key. -func (s Sparse[K, V]) Delete(k K) { +func (s *Sparse[K, V]) Delete(k K) { delete(s.store, k) // To know if the loop was run. @@ -68,19 +110,21 @@ func (s Sparse[K, V]) Delete(k K) { } } +// 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( -) iterx.PairChan[K, V] { +) chan V { keys := s.keys store := s.store - ret := make(iterx.PairChan[K, V]) + ret := make(chan V) go func() { for _, k := range keys { - ret <- iterx.Pair[K, V]{ - K: k, - V: store[k], - } + ret <- store[k] } close(ret) }() @@ -88,7 +132,33 @@ func (s *Sparse[K, V]) Chan( return ret } -// Sort the keys. +// 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]