From 1c5fcf1da1b0fbd1795baacab6f819d7f5691865 Mon Sep 17 00:00:00 2001 From: surdeus Date: Sat, 28 Oct 2023 14:26:50 +0300 Subject: [PATCH] Move sparse to the maps. --- cmd/sparse/main.go | 4 +- maps/main.go | 144 +++++++++++++++++++++++++++++++++ {mapx => maps}/misc.go | 2 +- maps/ordered.go | 103 +++++++++++++++++++++++ sparses/m.go => maps/sparse.go | 32 +++++--- maps/uniq.go | 113 ++++++++++++++++++++++++++ mapx/main.go | 58 ------------- mapx/ordered.go | 76 ----------------- mapx/uniq.go | 37 --------- poolx/main.go | 46 ----------- slicex/main.go | 35 -------- sparses/m_test.go | 15 ---- sparses/sparse.go | 25 ------ 13 files changed, 386 insertions(+), 304 deletions(-) create mode 100644 maps/main.go rename {mapx => maps}/misc.go (90%) create mode 100644 maps/ordered.go rename sparses/m.go => maps/sparse.go (88%) create mode 100644 maps/uniq.go delete mode 100644 mapx/main.go delete mode 100644 mapx/ordered.go delete mode 100644 mapx/uniq.go delete mode 100644 poolx/main.go delete mode 100644 slicex/main.go delete mode 100644 sparses/m_test.go delete mode 100644 sparses/sparse.go diff --git a/cmd/sparse/main.go b/cmd/sparse/main.go index de46156..836aa0f 100644 --- a/cmd/sparse/main.go +++ b/cmd/sparse/main.go @@ -1,12 +1,12 @@ package main import ( - "github.com/reklesio/gods/sparses" + "github.com/reklesio/gods/maps" "fmt" ) func main() { - arr := sparses.New[float32, string]("default", map[float32] string { + arr := maps.NewSparse[float32, string]("default", map[float32] string { 5: "something at 5", 12: "new shit 12", 50: "die 50", diff --git a/maps/main.go b/maps/main.go new file mode 100644 index 0000000..3c51393 --- /dev/null +++ b/maps/main.go @@ -0,0 +1,144 @@ +package maps + +import ( + "fmt" + "github.com/reklesio/gods" +) + +// Generic map interface for all the maps. +type Map[K comparable, V any] interface { + gods.Container[V] + + // Returns if the map has the key set. + Has(K) bool + + // Get the value and if the key is not set panic. + Get(K) V + + // The Go way to get values without panicing. + Got(K) (V, bool) + + // Set the value or reset if it is already set. + Set(K, V) + + // Delete the key no matter it exists or not. + Del(K) + + // Returns slice of values. + // For the order look the comment + // for "Keys()". + Values() []V + + // Get the values channel. + Chan() chan V + + // Returns slice of keys. + // Order is not guaranteed if + // the is not specified otherwise + // like for the NewOrdered. + Keys() []K + + KeyChan() chan K + + // The function to range over the values + // with the keys. + /*Range() chan struct{ + K K + V V + }*/ +} +type lMap[K comparable, V any] struct { + store map[K] V +} + +// Returns new basic map with the builtin Go type down there. +// Has all the features of the builtin Go maps and same performance. +func New[K comparable, V any]() Map[K, V] { + ret := &lMap[K, V]{} + ret.store = map[K]V{} + return ret +} + +func (m *lMap[K, V]) Clear() { + m.store = map[K]V{} +} + +func (m *lMap[K, V]) Keys() []K { + r := make([]K, len(m.store)) + i := 0 + for k := range m.store { + r[i] = k + i++ + } + + return r +} + +func (m *lMap[K, V]) Empty() bool { + return len(m.store) == 0 +} + +func (m *lMap[K, V]) Del(key K) { + delete(m.store, key) +} + +func (m *lMap[K, V]) Values() []V { + r := make([]V, len(m.store)) + i := 0 + for _, v := range m.store { + r[i] = v + i++ + } + + return r +} + +func (m *lMap[K, V]) Chan() chan V { + ret := make(chan V) + go func() { + for _, v := range m.store { + ret <- v + } + close(ret) + }() + return ret +} + +func (m *lMap[K, V]) Has(k K) bool { + _, ok := m.store[k] + return ok +} + +func (m *lMap[K, V]) Set(k K, v V) { + m.store[k] = v +} + +func (m *lMap[K, V]) Get(key K) V { + v, ok := m.store[key] + if !ok { + panic(fmt.Sprintf("there is no such key '%v'", key)) + } + return v +} + +func (m *lMap[K, V]) Got(key K) (V, bool) { + v, ok := m.store[key] + return v, ok +} + +func (m *lMap[K, V]) Size() int { + return len(m.store) +} + +func (m *lMap[K, V]) KeyChan() chan K { + ret := make(chan K) + go func() { + for k := range m.store { + ret <- k + } + close(ret) + }() + return ret +} + + diff --git a/mapx/misc.go b/maps/misc.go similarity index 90% rename from mapx/misc.go rename to maps/misc.go index 2499c53..c49ba9e 100644 --- a/mapx/misc.go +++ b/maps/misc.go @@ -1,4 +1,4 @@ -package mapx +package maps func Reversed[K, V comparable](m map[K] V) map[V] K { r := make(map[V] K) diff --git a/maps/ordered.go b/maps/ordered.go new file mode 100644 index 0000000..07b3abb --- /dev/null +++ b/maps/ordered.go @@ -0,0 +1,103 @@ +package maps + +// The type makes the underlying map ordered, +// so every time you pass through all the values +// they will be in the same order. +type orderedMap[K comparable, V any] struct { + store map[K] V + keys []K +} + +// Returns the new empty ordered map. +func NewOrdered[K comparable, V any]() Map[K, V] { + return &orderedMap[K, V]{ + store: make(map[K] V), + } +} + +func (m *orderedMap[K, V]) Clear() { + m.store = map[K]V{} + m.keys = []K{} +} + +func (m *orderedMap[K, V]) Set(k K, v V) { + _, ok := m.store[k] + if !ok { + m.keys = append(m.keys, k) + } + + m.store[k] = v +} + +func (m *orderedMap[K, V]) Got(key K) (V, bool) { + v, ok := m.store[key] + return v, ok +} + +func (m *orderedMap[K, V]) Has(k K) bool { + _, ok := m.store[k] + return ok +} + +// Get the value from the map. +func (m *orderedMap[K, V]) Get(k K) (V) { + v := m.store[k] + return v +} + +func (m *orderedMap[K, V]) Del(k K) { + delete(m.store, k) + for i, v := range m.keys { + if v == k { + m.keys = append(m.keys[:i], m.keys[i+1:]...) + } + } +} + +// Get map keys slice. +func (m *orderedMap[K, V]) Keys() []K { + return m.keys +} + +func (m *orderedMap[K, V]) Values() []V { + ret := make([]V, len(m.keys)) + i := 0 + for _, k := range m.keys { + ret[i] = m.store[k] + i++ + } + return ret +} + +func (m *orderedMap[K, V]) KeyChan() chan K { + chn := make(chan K) + go func() { + for _, v := range m.keys { + chn <- v + } + close(chn) + }() + return chn +} + +// Return channel of ordered values. +func (m *orderedMap[K, V]) Chan() chan V { + chn := make(chan V) + go func(){ + for _, k := range m.keys { + chn <- m.Get(k) + } + close(chn) + }() + + return chn +} + +func (m *orderedMap[K, V]) Empty() bool { + return len(m.keys) == 0 +} + +func (m *orderedMap[K, V]) Size() int { + return len(m.keys) +} + diff --git a/sparses/m.go b/maps/sparse.go similarity index 88% rename from sparses/m.go rename to maps/sparse.go index 94eb164..7607653 100644 --- a/sparses/m.go +++ b/maps/sparse.go @@ -1,4 +1,4 @@ -package sparses +package maps import ( "slices" @@ -27,10 +27,10 @@ type mSparse[K cmp.Ordered, V any] struct { // 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]( +func NewSparse[K cmp.Ordered, V any]( defval V, values ...map[K] V, -) Sparse[K, V] { +) Map[K, V] { var ( store map[K] V @@ -81,10 +81,6 @@ func (s *mSparse[K, V]) Has(key K) bool { 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 { @@ -93,6 +89,14 @@ func (s *mSparse[K, V]) Get(key K) (V) { return val } +func (s *mSparse[K, V]) Got(key K) (V, bool) { + v, ok := s.store[key] + if !ok { + v = s.def + } + return v, ok +} + func (s *mSparse[K, V]) Set(k K, v V) { _, ok := s.store[k] if !ok { @@ -107,7 +111,6 @@ 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) @@ -122,11 +125,11 @@ func (s *mSparse[K, V]) Del(k K) { } if idx != -1 { + // Removing the key. 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 @@ -143,6 +146,17 @@ func (s *mSparse[K, V]) Chan( return ret } +func (s *mSparse[K, V]) KeyChan() chan K { + ret := make(chan K) + go func() { + for _, k := range s.keys { + ret <- k + } + close(ret) + }() + return ret +} + func (s *mSparse[K, V]) Keys() []K { return s.keys } diff --git a/maps/uniq.go b/maps/uniq.go new file mode 100644 index 0000000..d756ab2 --- /dev/null +++ b/maps/uniq.go @@ -0,0 +1,113 @@ +package maps + +// The type describing unique map +// where you can quickly get both +// value by key and vice versa. +type Uniq[K, V comparable] interface { + Map[K, V] + GetByValue(V) K +} + +type uniqMap[K, V comparable] struct { + store map[K] V + rstore map[V] K +} + +// The function returns map type where +// you can get, set and delete by value +// since it store everything as ONLY entity +// both for keys and values way. +// Use only when you do not care about the order. +func NewUniq[K, V comparable]() Uniq[K, V] { + return &uniqMap[K, V]{ + map[K] V{}, + map[V] K{}, + } +} + +func (m *uniqMap[K, V]) Empty() bool { + return len(m.store) == 0 +} + +func (m *uniqMap[K, V]) Clear() { + m.store = map[K] V{} + m.rstore = map[V] K{} +} + +func (m *uniqMap[K, V]) Has(k K) bool { + _, ok := m.store[k] + return ok +} + +func (m *uniqMap[K, V]) Set(k K, v V) { + m.store[k] = v + m.rstore[v] = k +} + +func (m *uniqMap[K, V]) Del(k K) { + v := m.store[k] + delete(m.store, k) + delete(m.rstore, v) +} + +func (m *uniqMap[K, V]) Get(k K) (V) { + v := m.store[k] + return v +} + +func (m *uniqMap[K, V]) Got(k K) (V, bool) { + v, ok := m.store[k] + return v, ok +} + +func (m *uniqMap[K, V]) Chan() chan V { + ret := make(chan V) + go func() { + for _, v := range m.store { + ret <- v + } + close(ret) + }() + return ret +} + +func (m *uniqMap[K, V]) Keys() []K { + ret := make([]K, len(m.store)) + i := 0 + for k := range m.store { + ret[i] = k + i++ + } + return ret +} + +func (m *uniqMap[K, V]) KeyChan() chan K { + ret := make(chan K) + go func() { + for k := range m.store { + ret <- k + } + close(ret) + }() + return ret +} + +func (m *uniqMap[K, V]) Values() []V { + ret := make([]V, len(m.store)) + i := 0 + for _, v := range m.store { + ret[i] = v + i++ + } + return ret +} + +func (m *uniqMap[K, V]) Size() int { + return len(m.store) +} + +func (m *uniqMap[K, V]) GetByValue(v V) (K) { + k := m.rstore[v] + return k +} + diff --git a/mapx/main.go b/mapx/main.go deleted file mode 100644 index d0590f5..0000000 --- a/mapx/main.go +++ /dev/null @@ -1,58 +0,0 @@ -package mapx - -import ( - "fmt" -) - -// The package implements some more specific -// map structures for special uses. -// Implemented mostly to be embedded to other structures. - -// General map type, wrap for the built-in one. -type Map[K comparable, V any] map[K] V - -// Returns new basic map. -func New[K comparable, V any]() Map[K, V] { - return make(Map[K, V]) -} - -// Returns slice of keys of the map. -func (m Map[K, V]) Keys() []K { - r := make([]K, 0, len(m)) - for k := range m { - r = append(r, k) - } - - return r -} - -// Returns slice of values of the map. -func (m Map[K, V]) Values(sm map[K] V) []V { - r := make([]V, 0, len(m)) - for _, v := range m { - r = append(r, v) - } - - return r -} - -// Checks if the map contains the key. -func (m Map[K, V]) Has(k K) bool { - _, ok := m[k] - return ok -} - -// Sets the new value by key or resets if it exists. -func (m Map[K, V]) Set(k K, v V) { - m[k] = v -} - -// Returns the value by key. Panics if there is no such key. -func (m Map[K, V]) Get(k K) V { - v, ok := m[k] - if !ok { - panic(fmt.Sprintf("there is no such key '%v'", k)) - } - return v -} - diff --git a/mapx/ordered.go b/mapx/ordered.go deleted file mode 100644 index ecce2eb..0000000 --- a/mapx/ordered.go +++ /dev/null @@ -1,76 +0,0 @@ -package mapx - -// The type makes the underlying map ordered, -// so every time you pass through all the values -// they will be in the same order. -type OrderedMap[K comparable, V any] struct { - store map[K] V - keys []K -} - -// Returns the new empty ordered map. -func NewOrdered[K comparable, V any]() *OrderedMap[K, V] { - return &OrderedMap[K, V]{ - store: make(map[K] V), - } -} - -// Set or reset the value in the map. -func (m *OrderedMap[K, V]) Set(k K, v V) { - _, ok := m.store[k] - if !ok { - m.keys = append(m.keys, k) - } - - m.store[k] = v -} - -func (m *OrderedMap[K, V]) Has(k K) bool { - _, ok := m.store[k] - return ok -} - -// Get the value from the map. -func (m *OrderedMap[K, V]) Get(k K) (V) { - v := m.store[k] - return v -} - -func (m *OrderedMap[K, V]) Del(k K) { - delete(m.store, k) - for i, v := range m.keys { - if v == k { - m.keys = append(m.keys[:i], m.keys[i+1:]...) - } - } -} - -// Get map keys slice. -func (m *OrderedMap[K, V]) Keys() []K { - return m.keys -} - -func (m *OrderedMap[K, V]) KeyChan() chan K { - chn := make(chan K) - go func() { - for _, v := range m.keys { - chn <- v - } - close(chn) - }() - return chn -} - -// Return channel of ordered values. -func (m *OrderedMap[K, V]) Chan() chan V { - chn := make(chan V) - go func(){ - for _, k := range m.keys { - chn <- m.Get(k) - } - close(chn) - }() - - return chn -} - diff --git a/mapx/uniq.go b/mapx/uniq.go deleted file mode 100644 index a643e26..0000000 --- a/mapx/uniq.go +++ /dev/null @@ -1,37 +0,0 @@ -package mapx - -// The type implements map type where -// you can get, set and delete by value -// since it store everything as ONLY entity -// both for keys and values way. -// Use only when you do not care about the order. -type UniqMap[K, V comparable] struct { - store map[K] V - rstore map[V] K -} - -// Returns new empty UniqMap. -func NewUniq[K, V comparable]() *UniqMap[K, V] { - return &UniqMap[K, V]{ - make(map[K] V), - make(map[V] K), - } -} - -// Sets new value v for the k key. -func (m *UniqMap[K, V]) Set(k K, v V) { - m.store[k] = v - m.rstore[v] = k -} - -// Get value by the k key. -func (m *UniqMap[K, V]) Get(k K) (V, bool) { - v, ok := m.store[k] - return v, ok -} - -func (m *UniqMap[K, V]) GetByValue(v V) (K, bool) { - k, ok := m.rstore[v] - return k, ok -} - diff --git a/poolx/main.go b/poolx/main.go deleted file mode 100644 index 102661f..0000000 --- a/poolx/main.go +++ /dev/null @@ -1,46 +0,0 @@ -package poolx - -import ( - "github.com/mojosa-software/godat/src/llx" - "github.com/mojosa-software/godat/src/iterx" -) - -// Ordered value-only based structure. -// Fast deleting by value. -// Cannot store multiple equal values. - -type Pool[V comparable] struct { - store *llx.LinkedList[V] -} - -// Return new empty pool. -func New[V comparable]() *Pool[V] { - return &Pool[V]{ - store: llx.New[V](), - } -} - -func (p *Pool[V]) Append(v V) { - p.store.Append(v) -} - -// Deletes the first appearance of the value in the list. -func (p *Pool[V]) DeleteValue(v V) bool { - i := 0 - ll := p.store - for e := ll.First() ; e != nil ; e = e.Next() { - if e.Value() == v { - ll.Delete(i) - return true - } - - i++ - } - - return false -} - -func (p *Pool[V]) Chan() iterx.PairChan[int, V] { - return p.store.Chan() -} - diff --git a/slicex/main.go b/slicex/main.go deleted file mode 100644 index a0daa8d..0000000 --- a/slicex/main.go +++ /dev/null @@ -1,35 +0,0 @@ -package slicex - -func MakeMap[K comparable, V any]( - values []V, - fn func([]V, int) (K), -) map[K] V { - var k K - - r := make(map[K] V) - for i, _ := range values { - k = fn(values, i) - r[k] = values[i] - } - - return r -} - -func ConvStr[V1, V2 ~string](v1 []V1) []V2 { - ret := []V2{} - for i := range v1 { - ret = append(ret, V2(v1[i])) - } - - return ret -} - -func ConvInt[V1, V2 ~int](v1 []V1) []V2 { - ret := []V2{} - for i := range v1 { - ret = append(ret, V2(v1[i])) - } - - return ret -} - diff --git a/sparses/m_test.go b/sparses/m_test.go deleted file mode 100644 index ff9adab..0000000 --- a/sparses/m_test.go +++ /dev/null @@ -1,15 +0,0 @@ -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] -} diff --git a/sparses/sparse.go b/sparses/sparse.go deleted file mode 100644 index 5009cda..0000000 --- a/sparses/sparse.go +++ /dev/null @@ -1,25 +0,0 @@ -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 -} -