Skip to content

Commit

Permalink
Dev
Browse files Browse the repository at this point in the history
  • Loading branch information
lindsaygelle committed Oct 19, 2023
1 parent 6f1de91 commit 9bc4a45
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 25 deletions.
51 changes: 32 additions & 19 deletions hashtable.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ func (hashtable *Hashtable[K, V]) DeleteMany(keys ...K) *Hashtable[K, V] {

// DeleteManyOK deletes multiple keys from the hashtable and returns a slice of booleans indicating whether each deletion was successful.
// For each specified key, it checks if the key exists in the hashtable before attempting deletion. If the key does not exist,
// the deletion is considered successful for that key, and true is appended to the returned slice. If the key exists and is successfully
// the deletion is considered unsuccessful for that key, and false is appended to the returned slice. If the key exists and is successfully
// deleted, true is appended; otherwise, false is appended.
//
// Example:
Expand Down Expand Up @@ -540,38 +540,51 @@ func (hashtable *Hashtable[K, V]) Length() int {
return len(*hashtable)
}

// Map applies a given function to all key-value pairs in the hashtable and returns a new hashtable with the transformed values.
// The original hashtable remains unchanged.
// Map iterates over the key-value pairs in the hashtable and applies the provided function to each pair.
// The function can modify the value. The modified key-value pairs are updated in the same hashtable.
//
// Example:
//
// ht := make(hashtable.Hashtable[string, int])
// ht.Add("apple", 5)
// ht.Add("banana", 3)
// ht.Add("cherry", 8)
//
// // Define a function to double the values.
// doubleValue := func(key string, value int) int {
// return value * 2
// }
//
// // Apply the function to double the values in the hashtable.
// doubledHT := ht.Map(doubleValue)
// // doubledHT contains: {"apple": 10, "banana": 6, "cherry": 16}
// ht.Map(func(key string, value int) int {
// if key == "banana" {
// return value * 2 // Modify the value for the "banana" key
// }
// return value // Leave other values unchanged
// })
// // ht: {"apple": 5, "banana": 6}
func (hashtable *Hashtable[K, V]) Map(fn func(key K, value V) V) *Hashtable[K, V] {
for key, value := range *hashtable {
hashtable.Add(key, fn(key, value))
}
return hashtable
return hashtable.MapBreak(func(key K, value V) (V, bool) {
return fn(key, value), true
})
}

// MapBreak iterates over the key-value pairs in the hashtable and applies the provided function to each pair.
// The function can modify the value and return a boolean indicating whether to continue the iteration.
// If the function returns false, the iteration breaks, and a new hashtable with modified key-value pairs is returned.
//
// Example:
//
// ht := make(hashtable.Hashtable[string, int])
// ht.Add("apple", 5)
// ht.Add("banana", 3)
// newHT := ht.MapBreak(func(key string, value int) (int, bool) {
// if key == "banana" {
// return value * 2, false // Break the iteration when key is "banana"
// }
// return value, true // Continue iterating for other keys
// })
// // newHT: {"apple": 5}
func (hashtable *Hashtable[K, V]) MapBreak(fn func(key K, value V) (V, bool)) *Hashtable[K, V] {
newHashtable := make(Hashtable[K, V])
for key, value := range *hashtable {
value, ok := fn(key, value)
if !ok {
break
}
hashtable.Add(key, value)
newHashtable.Add(key, value)
}
return hashtable
return &newHashtable
}
75 changes: 69 additions & 6 deletions hashtable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func TestAddManyOK(t *testing.T) {
// Verify that the obtained results match the expected results.
for i, result := range *results {
if result != expectedResults[i] {
t.Errorf("Expected result: %v, but got: %v", expectedResults[i], result)
t.Fatalf("Expected result: %v, but got: %v", expectedResults[i], result)
}
}

Expand All @@ -184,7 +184,7 @@ func TestAddManyOK(t *testing.T) {
// Verify that the obtained results match the expected results.
for i, result := range *results {
if result != expectedResults[i] {
t.Errorf("Expected result: %v, but got: %v", expectedResults[i], result)
t.Fatalf("Expected result: %v, but got: %v", expectedResults[i], result)
}
}
}
Expand Down Expand Up @@ -387,7 +387,7 @@ func TestDeleteManyOK(t *testing.T) {
// Check if results match the expected results.
for i, result := range *results {
if result != expectedResults[i] {
t.Errorf("Expected deletion of key %s to be %v but got %v", keysToDelete[i], expectedResults[i], result)
t.Fatalf("Expected deletion of key %s to be %v but got %v", keysToDelete[i], expectedResults[i], result)
}
}
}
Expand All @@ -404,19 +404,19 @@ func TestDeleteOK(t *testing.T) {
// Delete keys and check if deletion is successful.
deleted := ht.DeleteOK("apple")
if !deleted {
t.Errorf("Expected deletion of 'apple' to be successful")
t.Fatalf("Expected deletion of 'apple' to be successful")
}

// Attempt to delete a key that does not exist.
notDeleted := ht.DeleteOK("grape")
if !notDeleted {
t.Errorf("Expected deletion of 'grape' to be successful because the key does not exist")
t.Fatalf("Expected deletion of 'grape' to be successful because the key does not exist")
}

// Attempt to delete a key that has already been deleted.
alreadyDeleted := ht.DeleteOK("apple")
if !alreadyDeleted {
t.Errorf("Expected deletion of 'apple' to be successful even though it was already deleted")
t.Fatalf("Expected deletion of 'apple' to be successful even though it was already deleted")
}
}

Expand Down Expand Up @@ -729,6 +729,7 @@ func TestKeys(t *testing.T) {
}
}

// TestKeysFunc tests Hashtable.Keys.
func TestKeysFunc(t *testing.T) {
// Create a new hashtable.
ht := make(hashtable.Hashtable[string, int])
Expand All @@ -750,6 +751,7 @@ func TestKeysFunc(t *testing.T) {
}
}

// TestLength tests Hashtable.Length.
func TestLength(t *testing.T) {
// Create a new hashtable.
ht := make(hashtable.Hashtable[string, int])
Expand All @@ -768,3 +770,64 @@ func TestLength(t *testing.T) {
t.Fatalf("Expected length: %d, but got: %d", expectedLength, length)
}
}

func TestMap(t *testing.T) {
// Create a new hashtable.
ht := make(hashtable.Hashtable[string, int])

// Add key-value pairs to the hashtable.
ht["apple"] = 5
ht["banana"] = 3
ht["cherry"] = 8

// Define a function to double the values.
doubleValue := func(key string, value int) int {
return value * 2
}

// Apply the function to double the values in the hashtable.
doubledHT := ht.Map(doubleValue)

// Expected doubled values.
expectedValues := map[string]int{"apple": 10, "banana": 6, "cherry": 16}
for key, expectedValue := range expectedValues {
value, exists := (*doubledHT)[key]
if !exists || value != expectedValue {
t.Fatalf("Expected value %d for key %s, but got %d", expectedValue, key, value)
}
}

// Ensure the original hashtable remains unchanged.
for key, expectedValue := range expectedValues {
value, exists := ht[key]
if !exists || value != expectedValue/2 {
t.Fatalf("Expected original value %d for key %s, but got %d", expectedValue/2, key, value)
}
}
}

// TestMapBreak tests Hashtable.MapBreak.
func TestMapBreak(t *testing.T) {
// Create a new hashtable.
ht := make(hashtable.Hashtable[string, int])

// Add key-value pairs to the hashtable.
ht["banana"] = 3

// Apply the MapBreak function to modify values and break the iteration at "banana".
ht.MapBreak(func(key string, value int) (int, bool) {
if key == "banana" {
return value * 2, false // Break the iteration when key is "banana"
}
return value * 2, true // Continue iterating for other keys and double the values
})

// Check if values are not modified as expected.
expectedValues := map[string]int{"banana": 3}
for key, expectedValue := range expectedValues {
value, exists := ht.Get(key)
if !exists || value != expectedValue {
t.Fatalf("Expected value %d for key %s, but got %d", expectedValue, key, value)
}
}
}

0 comments on commit 9bc4a45

Please sign in to comment.