Changed the sparses package.
This commit is contained in:
parent
5ed3237e00
commit
c0031a3f71
8 changed files with 230 additions and 198 deletions
|
@ -1,20 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/mojosa-software/godat/mapx"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ord := mapx.NewOrdered[int, string]()
|
||||
ord.Set(1, "one")
|
||||
ord.Set(5, "five")
|
||||
ord.Set(2, "two")
|
||||
ord.Del(5)
|
||||
for v := range ord.Chan() {
|
||||
fmt.Println(v)
|
||||
}
|
||||
for k := range ord.KeyChan() {
|
||||
fmt.Println(k)
|
||||
}
|
||||
}
|
|
@ -1,20 +1,34 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/mojosa-software/godat/sparsex"
|
||||
"github.com/reklesio/gods/sparses"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
arr := sparsex.New[float64, string](map[float64] string {
|
||||
arr := sparses.New[float32, string]("default", map[float32] string {
|
||||
5: "something at 5",
|
||||
12: "new shit",
|
||||
50: "die",
|
||||
}).
|
||||
Default("<NIL>")
|
||||
|
||||
arr.Del(12)
|
||||
for v := range arr.Chan() {
|
||||
fmt.Println(v)
|
||||
12: "new shit 12",
|
||||
50: "die 50",
|
||||
})
|
||||
for i:=0 ; i<=50 ; i++ {
|
||||
fmt.Println(arr.Get(float32(i)))
|
||||
}
|
||||
fmt.Println(arr.Size())
|
||||
|
||||
arr.Del(5)
|
||||
arr.Del(12)
|
||||
arr.Del(50)
|
||||
for i:=0 ; i<=50 ; i++ {
|
||||
fmt.Println(arr.Get(float32(i)))
|
||||
}
|
||||
fmt.Println(arr.Size())
|
||||
|
||||
fmt.Printf("%v\n", arr)
|
||||
arr.Del(12)
|
||||
arr.Set(10, "at 10")
|
||||
arr.Set(100, "at 100")
|
||||
arr.Set(49, "at 100")
|
||||
arr.Set(48.5, "at 100")
|
||||
fmt.Printf("%v\n", arr)
|
||||
}
|
||||
|
|
2
go.mod
2
go.mod
|
@ -1,5 +1,5 @@
|
|||
module github.com/reklesio/gods
|
||||
|
||||
go 1.19
|
||||
go 1.21
|
||||
|
||||
require golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb // indirect
|
||||
|
|
165
sparses/m.go
Normal file
165
sparses/m.go
Normal file
|
@ -0,0 +1,165 @@
|
|||
package sparses
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"cmp"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 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 mSparse[K cmp.Ordered, V any] struct {
|
||||
store map[K] V
|
||||
def V
|
||||
keys []K
|
||||
}
|
||||
|
||||
// Return the new with the default implementation storing the values from the
|
||||
// map inside the structure. Is fast on creation and reading, but
|
||||
// slow on inserting and deleting. Takes only one or zero maps as input.
|
||||
// Panics otherwise.
|
||||
func New[K cmp.Ordered, V any](
|
||||
defval V,
|
||||
values ...map[K] V,
|
||||
) Sparse[K, V] {
|
||||
|
||||
var (
|
||||
store map[K] V
|
||||
keys []K
|
||||
vs map[K] V
|
||||
)
|
||||
if len(values) > 1 {
|
||||
panic("too many arguments")
|
||||
} else if len(values) == 1 {
|
||||
vs = values[0]
|
||||
}
|
||||
|
||||
if vs == nil {
|
||||
store = map[K] V{}
|
||||
keys = []K{}
|
||||
} else {
|
||||
store = make(map[K] V, len(vs))
|
||||
keys = make([]K, len(vs))
|
||||
i := 0
|
||||
for k, v := range vs {
|
||||
keys[i] = k
|
||||
store[k] = v
|
||||
i++
|
||||
}
|
||||
slices.Sort(keys)
|
||||
}
|
||||
|
||||
ret := &mSparse[K, V]{
|
||||
store: store,
|
||||
def: defval,
|
||||
keys: keys,
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *mSparse[K, V]) Size() int {
|
||||
return len(s.keys)
|
||||
}
|
||||
|
||||
func (s *mSparse[K, V]) Clear() {
|
||||
s.store = map[K]V{}
|
||||
s.keys = []K{}
|
||||
}
|
||||
|
||||
func (s *mSparse[K, V]) Has(key K) bool {
|
||||
_, ok := s.store[key]
|
||||
return ok
|
||||
}
|
||||
|
||||
// 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 *mSparse[K, V]) Get(key K) (V) {
|
||||
val, ok := s.store[key]
|
||||
if !ok {
|
||||
val = s.def
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func (s *mSparse[K, V]) Set(k K, v V) {
|
||||
_, ok := s.store[k]
|
||||
if !ok {
|
||||
s.keys = append(s.keys, k)
|
||||
s.sort()
|
||||
}
|
||||
|
||||
s.store[k] = v
|
||||
}
|
||||
|
||||
func (s *mSparse[K, V]) Empty() bool {
|
||||
return len(s.keys) == 0
|
||||
}
|
||||
|
||||
// Delete the value by the key.
|
||||
func (s *mSparse[K, V]) Del(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:]...)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns channel of pairs.
|
||||
func (s *mSparse[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
|
||||
}
|
||||
|
||||
func (s *mSparse[K, V]) Keys() []K {
|
||||
return s.keys
|
||||
}
|
||||
|
||||
func (s *mSparse[K, V]) Values() []V {
|
||||
ret := []V{}
|
||||
for v := range s.Chan() {
|
||||
ret = append(ret, v)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *mSparse[K, V]) String() string {
|
||||
return fmt.Sprintf("%#v", s.store)
|
||||
}
|
||||
|
||||
func (s *mSparse[K, V]) sort() {
|
||||
slices.Sort(s.keys)
|
||||
}
|
||||
|
15
sparses/m_test.go
Normal file
15
sparses/m_test.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
package sparses
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
s := New[int, string](0, nil)
|
||||
if aVal := s.Empty() ; if aVal != true {
|
||||
t.Errorf("Got %v expected %v", aVal, )
|
||||
}
|
||||
|
||||
s = New[int, string]
|
||||
}
|
25
sparses/sparse.go
Normal file
25
sparses/sparse.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
package sparses
|
||||
import (
|
||||
"github.com/reklesio/gods"
|
||||
"cmp"
|
||||
)
|
||||
|
||||
// The general sparse array type.
|
||||
type Sparse[K cmp.Ordered, V any] interface {
|
||||
gods.Container[V]
|
||||
// Returns slice of set values.
|
||||
Values() []V
|
||||
// Returns slice of set keys.
|
||||
Keys() []K
|
||||
// Set the key to the value.
|
||||
Set(K, V)
|
||||
// Get the value by the key.
|
||||
Get(K) V
|
||||
// Returns true if the key is set.
|
||||
Has(K) bool
|
||||
// Delete the value under the key.
|
||||
Del(K)
|
||||
// Returns channel of ordered values.
|
||||
Chan() chan V
|
||||
}
|
||||
|
167
sparsex/main.go
167
sparsex/main.go
|
@ -1,167 +0,0 @@
|
|||
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]
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in a new issue