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..229fcd6 --- /dev/null +++ b/array/associative/associative.go @@ -0,0 +1,59 @@ +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: []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, + }) +} + +// 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 { + 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 { + if p == 0 { + a.items = a.items[p:] + return true + } + a.items = append(a.items[: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..2d2073a --- /dev/null +++ b/array/associative/associative_test.go @@ -0,0 +1,70 @@ +package associative + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +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") + + 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.True(m.Delete(1)) + }) +}