From 5d5e8473dbe177621671620d35d81b64f7673c5b Mon Sep 17 00:00:00 2001 From: Rafael Date: Tue, 20 Sep 2022 00:59:28 -0300 Subject: [PATCH 1/3] feat: Add AssociativeArray PoC --- array/associative/README.md | 6 +++ array/associative/associative.go | 54 +++++++++++++++++++++++++++ array/associative/associative_test.go | 23 ++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 array/associative/README.md create mode 100644 array/associative/associative.go create mode 100644 array/associative/associative_test.go diff --git a/array/associative/README.md b/array/associative/README.md new file mode 100644 index 0000000..1824cd0 --- /dev/null +++ b/array/associative/README.md @@ -0,0 +1,6 @@ +# Associative Array + +## Useful Links +- [Associative Array](https://en.wikipedia.org/wiki/Associative_array) +- [Hash Table](https://en.wikipedia.org/wiki/Hash_table) +- [Search Tree](https://en.wikipedia.org/wiki/Search_tree) diff --git a/array/associative/associative.go b/array/associative/associative.go new file mode 100644 index 0000000..1cf3819 --- /dev/null +++ b/array/associative/associative.go @@ -0,0 +1,54 @@ +package associative + +type ( + // Array - Associative Array (aka Map) is a key-value + // data structure. + Array[K comparable, T any] struct { + items []item[K, T] + } + + item[K comparable, T any] struct { + key K + value *T + } +) + +// NewArray returns a associative array instance. +func NewArray[K comparable, T any]() *Array[K, T] { + return &Array[K, T]{ + items: make([]item[K, T], 10), + } +} + +// Put adds an item to current Associative Array. +func (a *Array[K, T]) Put(key K, value T) { + a.items = append(a.items, item[K, T]{ + key: key, + value: &value, + }) +} + +// Get retrieves an item associated with given Key. +func (a *Array[K, T]) Get(key K) *T { + for _, i := range a.items { + if i.key == key { + return i.value + } + } + + return nil +} + +// Delete removes an item from Associative Array, returns: +// - true: if item was found +// - false: if item wasn't found +func (a *Array[K, T]) Delete(key K) bool { + for p, i := range a.items { + if i.key == key { + a.items = append(a.items[0:p], a.items[p-1:]...) + return true + } + } + + return false +} diff --git a/array/associative/associative_test.go b/array/associative/associative_test.go new file mode 100644 index 0000000..6a108dd --- /dev/null +++ b/array/associative/associative_test.go @@ -0,0 +1,23 @@ +package associative + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestAssociativeArray(t *testing.T) { + require := require.New(t) + + m := NewArray[int, string]() + + m.Put(1, "um") + m.Put(2, "dois") + m.Put(3, "tres") + + require.False(m.Delete(120)) + require.True(m.Delete(3)) + + require.Equal("dois", *m.Get(2)) + require.Equal("um", *m.Get(1)) +} From 54f75ca01d5c87953aa65e9e6e108143d8ed2509 Mon Sep 17 00:00:00 2001 From: Rafael Date: Tue, 20 Sep 2022 19:54:54 -0300 Subject: [PATCH 2/3] feat: Add comment for big O notation --- array/associative/associative.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/array/associative/associative.go b/array/associative/associative.go index 1cf3819..ce23734 100644 --- a/array/associative/associative.go +++ b/array/associative/associative.go @@ -28,7 +28,8 @@ func (a *Array[K, T]) Put(key K, value T) { }) } -// Get retrieves an item associated with given Key. +// Get retrieves an item associated with given Key, +// currently O(n). func (a *Array[K, T]) Get(key K) *T { for _, i := range a.items { if i.key == key { From a06d1506003124b754a1ba913536efd23bb2221f Mon Sep 17 00:00:00 2001 From: Rafael Date: Tue, 20 Sep 2022 20:11:40 -0300 Subject: [PATCH 3/3] fix: item fields are now exported --- array/associative/associative.go | 22 ++++++---- array/associative/associative_test.go | 61 ++++++++++++++++++++++++--- 2 files changed, 67 insertions(+), 16 deletions(-) diff --git a/array/associative/associative.go b/array/associative/associative.go index ce23734..229fcd6 100644 --- a/array/associative/associative.go +++ b/array/associative/associative.go @@ -8,23 +8,23 @@ type ( } item[K comparable, T any] struct { - key K - value *T + Key K + Value *T } ) // NewArray returns a associative array instance. func NewArray[K comparable, T any]() *Array[K, T] { return &Array[K, T]{ - items: make([]item[K, T], 10), + items: []item[K, T]{}, } } // Put adds an item to current Associative Array. func (a *Array[K, T]) Put(key K, value T) { a.items = append(a.items, item[K, T]{ - key: key, - value: &value, + Key: key, + Value: &value, }) } @@ -32,8 +32,8 @@ func (a *Array[K, T]) Put(key K, value T) { // currently O(n). func (a *Array[K, T]) Get(key K) *T { for _, i := range a.items { - if i.key == key { - return i.value + if i.Key == key { + return i.Value } } @@ -45,8 +45,12 @@ func (a *Array[K, T]) Get(key K) *T { // - false: if item wasn't found func (a *Array[K, T]) Delete(key K) bool { for p, i := range a.items { - if i.key == key { - a.items = append(a.items[0:p], a.items[p-1:]...) + if i.Key == key { + if p == 0 { + a.items = a.items[p:] + return true + } + a.items = append(a.items[:p], a.items[p-1:]...) return true } } diff --git a/array/associative/associative_test.go b/array/associative/associative_test.go index 6a108dd..2d2073a 100644 --- a/array/associative/associative_test.go +++ b/array/associative/associative_test.go @@ -6,18 +6,65 @@ import ( "github.com/stretchr/testify/require" ) -func TestAssociativeArray(t *testing.T) { +func TestNew(t *testing.T) { require := require.New(t) m := NewArray[int, string]() + require.NotNil(m) + require.NotNil(m.items) +} + +func TestPut(t *testing.T) { + require := require.New(t) + m := NewArray[int, string]() + + expectedValue := "um" + m.Put(1, expectedValue) + + require.NotNil(m.items[0].Value) + require.Equal(*m.items[0].Value, expectedValue) +} + +func TestGet(t *testing.T) { + m := NewArray[int, string]() + + t.Run("Empty Array", func(t *testing.T) { + require := require.New(t) + + require.Nil(m.Get(1)) + }) + + t.Run("With item", func(t *testing.T) { + m.Put(1, "um") + t.Run("Wrong key", func(t *testing.T) { + require := require.New(t) + + require.Nil(m.Get(2)) + }) + + t.Run("Found", func(t *testing.T) { + require := require.New(t) + + require.NotNil(m.Get(1)) + }) + }) +} + +func TestDelete(t *testing.T) { + m := NewArray[int, string]() + m.Put(1, "um") - m.Put(2, "dois") - m.Put(3, "tres") - require.False(m.Delete(120)) - require.True(m.Delete(3)) + t.Run("Wrong Key", func(t *testing.T) { + require := require.New(t) + + require.False(m.Delete(20)) + }) + + t.Run("Found", func(t *testing.T) { + require := require.New(t) - require.Equal("dois", *m.Get(2)) - require.Equal("um", *m.Get(1)) + require.True(m.Delete(1)) + }) }