From eddf2c345cb75e106d53ad910fed3ca10edd9542 Mon Sep 17 00:00:00 2001 From: surdeus Date: Fri, 17 Feb 2023 18:08:25 +0500 Subject: [PATCH] Implemented basic sparse array. --- go.mod | 2 + go.sum | 2 + src/cmd/sparse/main.go | 23 ++++++++++ src/sparsex/main.go | 95 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+) create mode 100644 go.sum create mode 100644 src/cmd/sparse/main.go create mode 100644 src/sparsex/main.go diff --git a/go.mod b/go.mod index 158fc3a..1762160 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/surdeus/godat go 1.19 + +require golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..90d0187 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb h1:PaBZQdo+iSDyHT053FjUCgZQ/9uqVwPOcl7KSWhKn6w= +golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= diff --git a/src/cmd/sparse/main.go b/src/cmd/sparse/main.go new file mode 100644 index 0000000..34a61d4 --- /dev/null +++ b/src/cmd/sparse/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "github.com/surdeus/godat/src/sparsex" + "fmt" +) + +func main() { + unord := sparsex.New[int, string](true) + unord.Set(1, "suck") + unord.Set(-5, "cock") + unord.Set(-4, "die") + unord.Set(-1000, "withme") + + for v := range unord.Vals() { + fmt.Println(v.K, v.V) + } + + unord.Sort() + for v := range unord.Vals() { + fmt.Println(v.K, v.V) + } +} diff --git a/src/sparsex/main.go b/src/sparsex/main.go new file mode 100644 index 0000000..bcfcb3f --- /dev/null +++ b/src/sparsex/main.go @@ -0,0 +1,95 @@ +package sparsex + +import ( + "sort" + cons "golang.org/x/exp/constraints" +) + +// The package implements a simple ordered map. +// In fact can be used as a sparse array so it is +// where the name comes from. + +type Pair[K cons.Ordered, V any] struct { + K K + V V +} + +type Sparse[K cons.Ordered, V any] struct { + store map[K] V + keys []K + shouldSort bool +} + +// Returns new sparse array +func New[K cons.Ordered, V any](s bool) *Sparse[K, V] { + return &Sparse[K, V]{ + store: make(map[K] V), + keys: []K{}, + shouldSort: s, + } +} + + +func (s *Sparse[K, V]) Get(key K) (V, bool) { + val, ok := s.store[key] + return val, ok +} + +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 +} + +func (s Sparse[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:]...) + if s.shouldSort { + s.Sort() + } + } +} + +func (s *Sparse[K, V]) Vals( +) chan Pair[K, V] { + keys := s.keys + store := s.store + ret := make(chan Pair[K, V]) + + go func() { + for _, v := range keys { + ret <- Pair[K, V]{ + v, store[v], + } + } + close(ret) + }() + + return ret +} + +// Sort the keys. +func (s *Sparse[K, V]) Sort() { + sort.Slice(s.keys, func(i, j int) bool { + return s.keys[i] < s.keys[j] + }) +} +