Skip to content

Commit

Permalink
Dev (#16)
Browse files Browse the repository at this point in the history
* Dev
  • Loading branch information
lindsaygelle authored Oct 17, 2023
1 parent e440467 commit d2d1b99
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 1 deletion.
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")
}
}

0 comments on commit d2d1b99

Please sign in to comment.