Skip to content

Commit

Permalink
Dev
Browse files Browse the repository at this point in the history
  • Loading branch information
lindsaygelle committed Oct 26, 2023
1 parent 048bd31 commit 38be94a
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 9 deletions.
59 changes: 53 additions & 6 deletions hashtable.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,23 @@ func (hashtable *Hashtable[K, V]) EachValueBreak(fn func(value V) bool) *Hashtab
})
}

// EmptyInto transfers all key-value pairs from the current hashtable into another hashtable, emptying the current hashtable.
// It takes another hashtable as input and adds all key-value pairs from the current hashtable to the other hashtable.
//
// // Create a new Hashtable instance.
// ht1 := make(Hashtable[string, int])
// ht1.Add("apple", 5)
// // Create a new Hashtable instance.
// ht2 := make(Hashtable[string, int])
//
// ht1.EmptyInto(ht2) // Transfers "apple": 5 from ht1 to ht2, leaving ht1 empty
func (hashtable *Hashtable[K, V]) EmptyInto(otherHashtable *Hashtable[K, V]) *Hashtable[K, V] {
hashtable.Each(func(key K, value V) {
otherHashtable.Add(key, hashtable.Pop(key))
})
return hashtable
}

// Equal checks if the current hashtable is equal to another hashtable by comparing the key-value pairs directly using reflect.DeepEqual.
// It takes another hashtable as input and returns true if the two hashtables are equal, false otherwise.
//
Expand Down Expand Up @@ -822,16 +839,28 @@ func (hashtable *Hashtable[K, V]) NotMany(keys ...K) *slice.Slice[bool] {
return &values
}

// Pop removes a key-value pair from the hashtable based on the provided key.
// Pop removes a key-value pair from the hashtable based on the provided key and returns the removed value.
// If the key is found in the hashtable, the corresponding value is returned. If the key is not present,
// the zero value for the value type is returned.
//
// ht := make(Hashtable[string, int])
// ht.Add("apple", 5)
// removedValue := ht.Pop("apple") // Removes the key "apple" and returns its associated value 5, or 0 if "apple" is not found
func (hashtable *Hashtable[K, V]) Pop(key K) V {
value, _ := hashtable.PopOK(key)
return value
}

// PopOK removes a key-value pair from the hashtable based on the provided key.
// It returns the removed value and a boolean indicating whether the key was found and removed successfully.
// If the key is present in the hashtable, the corresponding value is returned, and the key-value pair is deleted.
// If the key is not found, it returns the zero value for the value type and false.
//
// newHashtable := make(Hashtable[string, int])
// newHashtable.Add("apple", 5)
// removedValue, ok := newHashtable.Pop("apple") // Removes the key "apple" and returns its associated value 5, ok is true
// removedValue, ok = newHashtable.Pop("banana") // Key "banana" not found, removedValue is 0 and ok is false
func (hashtable *Hashtable[K, V]) Pop(key K) (V, bool) {
// removedValue, ok := newHashtable.PopOK("apple") // Removes the key "apple" and returns its associated value 5, ok is true
// removedValue, ok = newHashtable.PopOK("banana") // Key "banana" not found, removedValue is 0 and ok is false
func (hashtable *Hashtable[K, V]) PopOK(key K) (V, bool) {
value, ok := hashtable.Get(key)
if ok {
ok = hashtable.DeleteOK(key)
Expand All @@ -851,7 +880,7 @@ func (hashtable *Hashtable[K, V]) Pop(key K) (V, bool) {
func (hashtable *Hashtable[K, V]) PopMany(keys ...K) *slice.Slice[V] {
values := make(slice.Slice[V], 0)
for _, key := range keys {
value, ok := hashtable.Pop(key)
value, ok := hashtable.PopOK(key)
if ok {
values.Append(value)
}
Expand All @@ -874,7 +903,7 @@ func (hashtable *Hashtable[K, V]) PopManyFunc(fn func(key K, value V) bool) *sli
values := make(slice.Slice[V], 0)
hashtable.Each(func(key K, value V) {
if fn(key, value) {
removedValue, _ := hashtable.Pop(key)
removedValue := hashtable.Pop(key)
values.Append(removedValue)
}
})
Expand Down Expand Up @@ -906,6 +935,24 @@ func (hashtable *Hashtable[K, V]) ReplaceMany(fn func(key K, value V) (V, bool))
return hashtable
}

// TakeFrom transfers all key-value pairs from another hashtable into the current hashtable, emptying the other hashtable.
// It takes another hashtable as input and adds all key-value pairs from the other hashtable to the current hashtable.
//
// // Create a new Hashtable instance.
// ht1 := make(Hashtable[string, int])
// ht1.Add("apple", 5)
// // Create a new Hashtable instance.
// ht2 := make(Hashtable[string, int])
// ht2.Add("orange", 10)
//
// ht1.TakeFrom(ht2) // Transfers "orange": 10 from ht2 to ht1, leaving ht2 empty
func (hashtable *Hashtable[K, V]) TakeFrom(otherHashtable *Hashtable[K, V]) *Hashtable[K, V] {
otherHashtable.Each(func(key K, value V) {
hashtable.Add(key, otherHashtable.Pop(key))
})
return hashtable
}

// Values returns a slice containing all the values present in the hashtable.
// It iterates over the hashtable and collects all the values in the order of insertion.
//
Expand Down
116 changes: 113 additions & 3 deletions hashtable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,42 @@ func TestEachValueBreak(t *testing.T) {
}
}

// TestEmptyInto tests Hashtable.EmptyInto.
func TestEmptyInto(t *testing.T) {
// Test case 1: Transfer from an empty hashtable to another empty hashtable.
ht1 := &hashtable.Hashtable[string, int]{} // Create an empty source hashtable.
ht2 := &hashtable.Hashtable[string, int]{} // Create an empty destination hashtable.
ht1.EmptyInto(ht2) // Transfer from ht1 to ht2.

// Verify that ht1 is empty.
if ht1.Length() != 0 {
t.Errorf("Expected source hashtable to be empty after transfer, but it has %d items", ht1.Length())
}

// Verify that ht2 is still empty.
if ht2.Length() != 0 {
t.Errorf("Expected destination hashtable to be empty after transfer, but it has %d items", ht2.Length())
}

// Test case 2: Transfer from a non-empty hashtable to an empty hashtable.
ht1 = &hashtable.Hashtable[string, int]{} // Create an empty source hashtable.
ht1.Add("apple", 5)
ht2 = &hashtable.Hashtable[string, int]{} // Create an empty destination hashtable.
ht1.EmptyInto(ht2) // Transfer from ht1 to ht2.

// Verify that ht1 is empty.
if ht1.Length() != 0 {
t.Errorf("Expected source hashtable to be empty after transfer, but it has %d items", ht1.Length())
}

// Verify that ht2 contains the transferred key-value pair.
expectedValue := 5
transferredValue, ok := ht2.Get("apple")
if !ok || transferredValue != expectedValue {
t.Errorf("Expected destination hashtable to contain 'apple': %d after transfer, but it contains '%d'", expectedValue, transferredValue)
}
}

// TestEqual tests Hashtable.Equal.
func TestEqual(t *testing.T) {
// Test case 1: Compare equal hashtables.
Expand Down Expand Up @@ -1253,15 +1289,53 @@ func TestNot(t *testing.T) {
func TestPop(t *testing.T) {
// Test case 1: Pop from an empty hashtable.
ht := &hashtable.Hashtable[string, int]{} // Create an empty hashtable.
removedValue, ok := ht.Pop("apple")
removedValue := ht.Pop("apple")
expectedValue := 0 // No key "apple" in the empty hashtable.

if removedValue != expectedValue {
t.Errorf("Expected removed value to be %d, but got %d", expectedValue, removedValue)
}

// Test case 2: Pop from a non-empty hashtable where the key is present.
ht = &hashtable.Hashtable[string, int]{} // Create an empty hashtable.
ht.Add("apple", 5)
removedValue = ht.Pop("apple")
expectedValue = 5 // Key "apple" exists with value 5.

if removedValue != expectedValue {
t.Errorf("Expected removed value to be %d, but got %d", expectedValue, removedValue)
}
// Verify that the key is removed.
_, ok := ht.Get("apple")
if ok {
t.Errorf("Expected key 'apple' to be removed, but it was found")
}

// Test case 3: Pop from a non-empty hashtable where the key is not present.
ht = &hashtable.Hashtable[string, int]{} // Create an empty hashtable.
ht.Add("apple", 5)
ht.Add("orange", 10)
removedValue = ht.Pop("banana")
expectedValue = 0 // No key "banana" in the hashtable.

if removedValue != expectedValue {
t.Errorf("Expected removed value to be %d, but got %d", expectedValue, removedValue)
}
}

// TestPopOK tests Hashtable.PopOK.
func TestPopOK(t *testing.T) {
// Test case 1: Pop from an empty hashtable.
ht := &hashtable.Hashtable[string, int]{} // Create an empty hashtable.
removedValue, ok := ht.PopOK("apple")
if ok || removedValue != 0 {
t.Errorf("Expected (0, false), but got (%d, %v)", removedValue, ok)
}

// Test case 2: Pop from a non-empty hashtable where the key is present.
ht = &hashtable.Hashtable[string, int]{} // Create an empty hashtable.
ht.Add("apple", 5)
removedValue, ok = ht.Pop("apple")
removedValue, ok = ht.PopOK("apple")
if !ok || removedValue != 5 {
t.Errorf("Expected (5, true), but got (%d, %v)", removedValue, ok)
}
Expand All @@ -1275,7 +1349,7 @@ func TestPop(t *testing.T) {
ht = &hashtable.Hashtable[string, int]{} // Create an empty hashtable.
ht.Add("apple", 5)
ht.Add("orange", 10)
removedValue, ok = ht.Pop("banana")
removedValue, ok = ht.PopOK("banana")
if ok || removedValue != 0 {
t.Errorf("Expected (0, false), but got (%d, %v)", removedValue, ok)
}
Expand Down Expand Up @@ -1421,6 +1495,42 @@ func TestUpdate(t *testing.T) {
}
}

// TestTakeFrom tests Hashtable.TakeFrom.
func TestTakeFrom(t *testing.T) {
// Test case 1: Transfer from an empty hashtable to another empty hashtable.
ht1 := &hashtable.Hashtable[string, int]{} // Create an empty destination hashtable.
ht2 := &hashtable.Hashtable[string, int]{} // Create an empty source hashtable.
ht1.TakeFrom(ht2) // Transfer from ht2 to ht1.

// Verify that ht1 is still empty.
if ht1.Length() != 0 {
t.Errorf("Expected destination hashtable to be empty after transfer, but it has %d items", ht1.Length())
}

// Verify that ht2 is still empty.
if ht2.Length() != 0 {
t.Errorf("Expected source hashtable to be empty after transfer, but it has %d items", ht2.Length())
}

// Test case 2: Transfer from a non-empty hashtable to an empty hashtable.
ht1 = &hashtable.Hashtable[string, int]{} // Create an empty destination hashtable.
ht2 = &hashtable.Hashtable[string, int]{} // Create a source hashtable.
ht2.Add("orange", 10)
ht1.TakeFrom(ht2) // Transfer from ht2 to ht1.

// Verify that ht1 contains the transferred key-value pair.
expectedValue := 10
transferredValue, ok := ht1.Get("orange")
if !ok || transferredValue != expectedValue {
t.Errorf("Expected destination hashtable to contain 'orange': %d after transfer, but it contains '%d'", expectedValue, transferredValue)
}

// Verify that ht2 is empty after transfer.
if ht2.Length() != 0 {
t.Errorf("Expected source hashtable to be empty after transfer, but it has %d items", ht2.Length())
}
}

// TestValues tests Hashtable.Values.
func TestValues(t *testing.T) {
// Test case 1: Values of an empty hashtable should be an empty slice.
Expand Down

0 comments on commit 38be94a

Please sign in to comment.