Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #16

Merged
merged 2 commits into from
Oct 17, 2023
Merged

Dev #16

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/lindsaygelle/hashtable

go 1.21.1
go 1.21
73 changes: 73 additions & 0 deletions hashtable.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,76 @@ func (hashtable *Hashtable[K, V]) Add(key K, value V) *Hashtable[K, V] {
(*hashtable)[key] = value
return hashtable
}

// AddFunc inserts key-value pairs into the hashtable based on the provided maps and a custom validation function.
// The validation function should return true for key-value pairs that should be added to the hashtable, and false otherwise.
//
// Example:
// ht := make(hashtable.Hashtable[string, int])
// ht.AddFunc([]map[string]int{{"apple": 1, "orange": 2}}, func(key string, value int) bool {
// // Only add key-value pairs where the value is greater than 1.
// return value > 1
// })
func (hashtable *Hashtable[K, V]) AddFunc(values []map[K]V, fn func(key K, value V) bool) *Hashtable[K, V] {
for _, item := range values {
for key, value := range item {
if fn(key, value) {
hashtable.Add(key, value)
}
}
}
return hashtable
}

// AddMany inserts multiple key-value pairs into the hashtable from the provided maps.
// If keys already exist, their associated values are updated.
//
// Example:
// ht := make(hashtable.Hashtable[string, int])
// ht.AddMany(map[string]int{"orange": 7, "grape": 4}, map[string]int{"kiwi": 6, "pear": 9})
func (hashtable *Hashtable[K, V]) AddMany(values ...map[K]V) *Hashtable[K, V] {
for _, item := range values {
for key, value := range item {
hashtable.Add(key, value)
}
}
return hashtable
}

// Delete removes a key-value pair from the hashtable based on the provided key.
//
// Example:
// ht := make(hashtable.Hashtable[string, int])
// ht.Add("apple", 5)
// ht.Add("banana", 3)
// ht.Delete("apple") // Removes the key-value pair with key "apple" from the hashtable.
func (hashtable *Hashtable[K, V]) Delete(key K) *Hashtable[K, V] {
delete(*hashtable, key)
return hashtable
}

// Get retrieves the value associated with the provided key from the hashtable.
// If the key exists, it returns the associated value and true. Otherwise, it returns the zero value for the value type and false.
//
// Example:
// ht := make(hashtable.Hashtable[string, int])
// ht.Add("apple", 5)
// value, exists := ht.Get("apple") // 5, true
// value, exists = ht.Get("orange") // 0, false
func (hashtable *Hashtable[K, V]) Get(key K) (V, bool) {
value, ok := (*hashtable)[key]
return value, ok
}

// Has checks if the provided key exists in the hashtable.
// It returns true if the key exists, and false otherwise.
//
// Example:
// ht := make(hashtable.Hashtable[string, int])
// ht.Add("apple", 5)
// exists := ht.Has("apple") // true
// exists = ht.Has("orange") // false
func (hashtable *Hashtable[K, V]) Has(key K) bool {
_, ok := (*hashtable)[key]
return ok
}
131 changes: 131 additions & 0 deletions hashtable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,134 @@ func TestAdd(t *testing.T) {
t.Fatalf("Expected value for key 'banana' to be updated to 10, but got %d", ht["banana"])
}
}

// TestAddFunc tests Hashtable.AddFunc.
func TestAddFunc(t *testing.T) {
ht := make(hashtable.Hashtable[string, int])

// Test case 1: Add key-value pairs where the value is greater than 1
ht.AddFunc([]map[string]int{{"apple": 1, "orange": 2, "banana": 3}}, func(key string, value int) bool {
return value > 1
})

// Check if expected key-value pairs are added
expected := map[string]int{"orange": 2, "banana": 3}
for key, expectedValue := range expected {
value, exists := ht.Get(key)
if !exists || value != expectedValue {
t.Errorf("Expected key '%s' with value '%d', but got value '%d'", key, expectedValue, value)
}
}

// Test case 2: Add all key-value pairs without any validation
ht.AddFunc([]map[string]int{{"kiwi": 0, "pear": 4}}, func(key string, value int) bool {
return true
})

// Check if all key-value pairs are added
allValues := map[string]int{"orange": 2, "banana": 3, "kiwi": 0, "pear": 4}
for key, expectedValue := range allValues {
value, exists := ht.Get(key)
if !exists || value != expectedValue {
t.Errorf("Expected key '%s' with value '%d', but got value '%d'", key, expectedValue, value)
}
}
}

// TestAddMany tests Hashtable.AddMany

func TestAddMany(t *testing.T) {
ht := make(hashtable.Hashtable[string, int])

// Test case 1
ht.AddMany(map[string]int{"orange": 7, "grape": 4})
expected1 := 7
if val, ok := ht["orange"]; !ok || val != expected1 {
t.Errorf("Expected %d, but got %d for key 'orange'", expected1, val)
}
expected2 := 4
if val, ok := ht["grape"]; !ok || val != expected2 {
t.Errorf("Expected %d, but got %d for key 'grape'", expected2, val)
}

// Test case 2
ht.AddMany(map[string]int{"kiwi": 6, "pear": 9})
expected3 := 6
if val, ok := ht["kiwi"]; !ok || val != expected3 {
t.Errorf("Expected %d, but got %d for key 'kiwi'", expected3, val)
}
expected4 := 9
if val, ok := ht["pear"]; !ok || val != expected4 {
t.Errorf("Expected %d, but got %d for key 'pear'", expected4, val)
}
}

// TestDelete tests Hashtable.Delete
func TestDelete(t *testing.T) {
ht := make(hashtable.Hashtable[string, int])
ht["apple"] = 5
ht["banana"] = 3

// Test case 1: Delete an existing key
ht.Delete("apple")
if _, ok := ht["apple"]; ok {
t.Errorf("Expected key 'apple' to be deleted, but it still exists in the hashtable")
}

// Test case 2: Delete a non-existing key
ht.Delete("nonexistent")
if _, ok := ht["nonexistent"]; ok {
t.Errorf("Expected key 'nonexistent' to not exist, but it was found in the hashtable")
}

// Test case 3: Delete a key after adding it again
ht["apple"] = 10
ht.Delete("apple")
if _, ok := ht["apple"]; ok {
t.Errorf("Expected key 'apple' to be deleted, but it still exists in the hashtable")
}
}

// TestGet tests Hashtable.Get

func TestGet(t *testing.T) {
ht := make(hashtable.Hashtable[string, int])
ht["apple"] = 5
ht["banana"] = 3

// Test case 1: Get an existing key
value, exists := ht.Get("apple")
if !exists {
t.Errorf("Expected key 'apple' to exist, but it was not found in the hashtable")
}
if value != 5 {
t.Errorf("Expected value for key 'apple' to be 5, but got %d", value)
}

// Test case 2: Get a non-existing key
value, exists = ht.Get("orange")
if exists {
t.Errorf("Expected key 'orange' to not exist, but it was found in the hashtable with value %d", value)
}
if value != 0 {
t.Errorf("Expected default value for non-existing key 'orange' to be 0, but got %d", value)
}
}

// TestHas tests Hashtable.Has

func TestHas(t *testing.T) {
ht := make(hashtable.Hashtable[string, int])
ht["apple"] = 5
ht["banana"] = 3

// Test case 1: Key exists in the hashtable
if !ht.Has("apple") {
t.Errorf("Expected key 'apple' to exist, but it was not found in the hashtable")
}

// Test case 2: Key does not exist in the hashtable
if ht.Has("orange") {
t.Errorf("Expected key 'orange' to not exist, but it was found in the hashtable")
}
}
Loading