-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ feat: add hashmap, hashset and stack unify functions #5
- Loading branch information
1 parent
45e0348
commit 1ebde5a
Showing
6 changed files
with
1,140 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package unify4go | ||
|
||
// HashMap is a generic hash map data structure that maps keys of type `K` to values of type `V`. | ||
// `K` and `V` must be comparable types, meaning that they support comparison operators (like == and !=). | ||
// The `items` field stores the actual map, which is used to store key-value pairs. | ||
type HashMap[K, V comparable] struct { | ||
items map[K]V | ||
} | ||
|
||
// NewHashMap is a constructor function that initializes and returns a pointer to a new, empty `HashMap`. | ||
// It creates a new map with keys of type `K` and values of type `V`. | ||
// | ||
// Generics are used to make this function flexible for any types of keys and values as long as they | ||
// are comparable. The function ensures that the map is properly initialized before returning it. | ||
// | ||
// Example usage: | ||
// | ||
// hashMap := NewHashMap[string, int]() // Creates a HashMap with string keys and int values. | ||
func NewHashMap[K, V comparable]() *HashMap[K, V] { | ||
hash := &HashMap[K, V]{ | ||
items: make(map[K]V), | ||
} | ||
return hash | ||
} | ||
|
||
// Put adds a new key-value pair to the HashMap. If the key already exists, its value is updated. | ||
// Parameters: | ||
// - `key`: The key to be added or updated in the map. | ||
// - `value`: The value to be associated with the key. | ||
// | ||
// Example: | ||
// | ||
// hashMap.Put("apple", 5) // Inserts or updates the value of "apple" to 5. | ||
func (hash *HashMap[K, V]) Put(key K, value V) { | ||
hash.items[key] = value | ||
} | ||
|
||
// Get retrieves the value associated with the given key from the HashMap. | ||
// If the key exists, it returns the corresponding value. If the key does not exist, it returns the zero value for the type `V`. | ||
// Parameters: | ||
// - `key`: The key whose associated value is to be returned. | ||
// | ||
// Returns: | ||
// - The value associated with the key, or the zero value for `V` if the key is not found. | ||
// | ||
// Example: | ||
// | ||
// value := hashMap.Get("apple") // Retrieves the value associated with "apple". | ||
func (hash *HashMap[K, V]) Get(key K) (value V) { | ||
return hash.items[key] | ||
} | ||
|
||
// Remove deletes the key-value pair from the HashMap for the specified key. | ||
// If the key does not exist, no action is taken. | ||
// Parameters: | ||
// - `key`: The key to be removed from the map. | ||
// | ||
// Example: | ||
// | ||
// hashMap.Remove("apple") // Removes the "apple" key and its associated value. | ||
func (hash *HashMap[K, V]) Remove(key K) { | ||
delete(hash.items, key) | ||
} | ||
|
||
// Clear removes all key-value pairs from the HashMap, effectively resetting it to an empty map. | ||
// | ||
// Example: | ||
// | ||
// hashMap.Clear() // Clears the map, removing all entries. | ||
func (hash *HashMap[K, V]) Clear() { | ||
hash.items = make(map[K]V) | ||
} | ||
|
||
// Size returns the number of key-value pairs currently stored in the HashMap. | ||
// Returns: | ||
// - The number of key-value pairs in the map. | ||
// | ||
// Example: | ||
// | ||
// size := hashMap.Size() // Gets the size of the map. | ||
func (hash *HashMap[K, V]) Size() int { | ||
return len(hash.items) | ||
} | ||
|
||
// IsEmpty checks if the HashMap is empty (i.e., contains no key-value pairs). | ||
// Returns: | ||
// - `true` if the map is empty, `false` otherwise. | ||
// | ||
// Example: | ||
// | ||
// isEmpty := hashMap.IsEmpty() // Returns true if the map is empty. | ||
func (hash *HashMap[K, V]) IsEmpty() bool { | ||
return len(hash.items) == 0 | ||
} | ||
|
||
// ContainsKey checks whether the specified key exists in the HashMap. | ||
// Parameters: | ||
// - `key`: The key to check for existence in the map. | ||
// | ||
// Returns: | ||
// - `true` if the key exists in the map, `false` otherwise. | ||
// | ||
// Example: | ||
// | ||
// exists := hashMap.ContainsKey("apple") // Checks if the key "apple" exists in the map. | ||
func (hash *HashMap[K, V]) ContainsKey(key K) bool { | ||
_, ok := hash.items[key] | ||
return ok | ||
} | ||
|
||
// KeySet returns a slice of all keys currently stored in the HashMap. | ||
// Returns: | ||
// - A slice containing all keys in the map. | ||
// | ||
// Example: | ||
// | ||
// keys := hashMap.KeySet() // Returns all the keys in the map. | ||
func (hash *HashMap[K, V]) KeySet() []K { | ||
keys := make([]K, hash.Size()) | ||
i := 0 | ||
for key := range hash.items { | ||
keys[i] = key | ||
} | ||
return keys | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,234 @@ | ||
package unify4go | ||
|
||
import "fmt" | ||
|
||
// itemExists is an empty struct used as a placeholder for values in the `HashSet` map. | ||
// Using an empty struct saves memory, as it does not allocate any space in Go. | ||
var itemExists struct{} | ||
|
||
// HashSet is a generic set data structure that stores unique elements of type `T`. | ||
// It is implemented using a map where the keys are the elements and the values are | ||
// empty structs (`struct{}`), which is an efficient way to represent a set in Go. | ||
// The type `T` must be comparable, meaning it can be compared using == and !=. | ||
type HashSet[T comparable] struct { | ||
items map[T]struct{} | ||
} | ||
|
||
// NewHashSet is a constructor function that creates a new `HashSet` and optionally adds | ||
// any provided elements to the set. | ||
// Parameters: | ||
// - `elements`: A variadic list of elements of type `T` to initialize the set with (optional). | ||
// | ||
// Returns: | ||
// - A pointer to the newly created `HashSet`. | ||
// | ||
// Example usage: | ||
// | ||
// hashSet := NewHashSet(1, 2, 3) // Creates a set with initial elements 1, 2, and 3. | ||
func NewHashSet[T comparable](elements ...T) *HashSet[T] { | ||
hash := &HashSet[T]{ | ||
items: make(map[T]struct{}), | ||
} | ||
hash.AddAll(elements...) | ||
return hash | ||
} | ||
|
||
// Add inserts a new element into the HashSet. If the element already exists, no action is taken. | ||
// Parameters: | ||
// - `element`: The element to be added to the set. | ||
// | ||
// Example usage: | ||
// | ||
// hashSet.Add(4) // Adds the element 4 to the set. | ||
func (hash *HashSet[T]) Add(element T) { | ||
hash.items[element] = itemExists | ||
} | ||
|
||
// AddAll inserts multiple elements into the HashSet. If any element already exists, it is ignored. | ||
// Parameters: | ||
// - `elements`: A variadic list of elements of type `T` to add to the set. | ||
// | ||
// Example usage: | ||
// | ||
// hashSet.AddAll(4, 5, 6) // Adds elements 4, 5, and 6 to the set. | ||
func (hash *HashSet[T]) AddAll(elements ...T) { | ||
for _, e := range elements { | ||
hash.Add(e) | ||
} | ||
} | ||
|
||
// Remove deletes the specified element from the HashSet. | ||
// If the element does not exist, no action is taken. | ||
// Parameters: | ||
// - `element`: The element to be removed from the set. | ||
// | ||
// Example usage: | ||
// | ||
// hashSet.Remove(5) // Removes element 5 from the set. | ||
func (hash *HashSet[T]) Remove(element T) { | ||
delete(hash.items, element) | ||
} | ||
|
||
// RemoveAll deletes multiple elements from the HashSet. | ||
// Parameters: | ||
// - `elements`: A variadic list of elements to be removed from the set. | ||
// | ||
// Example usage: | ||
// | ||
// hashSet.RemoveAll(2, 4, 6) // Removes elements 2, 4, and 6 from the set. | ||
func (hash *HashSet[T]) RemoveAll(elements ...T) { | ||
for _, e := range elements { | ||
hash.Remove(e) | ||
} | ||
} | ||
|
||
// Clear removes all elements from the HashSet, resetting it to an empty set. | ||
// | ||
// Example usage: | ||
// | ||
// hashSet.Clear() // Clears all elements from the set. | ||
func (hash *HashSet[T]) Clear() { | ||
hash.items = make(map[T]struct{}) | ||
} | ||
|
||
// Size returns the number of elements currently stored in the HashSet. | ||
// Returns: | ||
// - The number of elements in the set. | ||
// | ||
// Example usage: | ||
// | ||
// size := hashSet.Size() // Returns the size of the set. | ||
func (hash *HashSet[T]) Size() int { | ||
return len(hash.items) | ||
} | ||
|
||
// IsEmpty checks if the HashSet contains any elements. | ||
// Returns: | ||
// - `true` if the set is empty, `false` otherwise. | ||
// | ||
// Example usage: | ||
// | ||
// isEmpty := hashSet.IsEmpty() // Returns true if the set is empty. | ||
func (hash *HashSet[T]) IsEmpty() bool { | ||
return len(hash.items) == 0 | ||
} | ||
|
||
// Contains checks whether the specified element exists in the HashSet. | ||
// Parameters: | ||
// - `element`: The element to check for existence in the set. | ||
// | ||
// Returns: | ||
// - `true` if the element is present in the set, `false` otherwise. | ||
// | ||
// Example usage: | ||
// | ||
// exists := hashSet.Contains(3) // Checks if element 3 is in the set. | ||
func (hash *HashSet[T]) Contains(element T) bool { | ||
_, ok := hash.items[element] | ||
return ok | ||
} | ||
|
||
// Intersection returns a new HashSet containing only the elements present in both the current set and another set. | ||
// Parameters: | ||
// - `another`: Another `HashSet` to find the intersection with. | ||
// | ||
// Returns: | ||
// - A new `HashSet` containing the intersection of the two sets. | ||
// | ||
// Example usage: | ||
// | ||
// resultSet := hashSet.Intersection(anotherSet) // Returns the intersection of two sets. | ||
func (hash *HashSet[T]) Intersection(another *HashSet[T]) *HashSet[T] { | ||
result := NewHashSet[T]() | ||
if hash.Size() <= another.Size() { | ||
for item := range hash.items { | ||
if _, contains := another.items[item]; contains { | ||
result.Add(item) | ||
} | ||
} | ||
return result | ||
} | ||
for item := range another.items { | ||
if _, contains := hash.items[item]; contains { | ||
result.Add(item) | ||
} | ||
} | ||
return result | ||
} | ||
|
||
// Union returns a new HashSet that contains all elements from both the current set and another set. | ||
// Parameters: | ||
// - `another`: Another `HashSet` to combine with the current set. | ||
// | ||
// Returns: | ||
// - A new `HashSet` containing the union of the two sets. | ||
// | ||
// Example usage: | ||
// | ||
// resultSet := hashSet.Union(anotherSet) // Returns the union of two sets. | ||
func (hash *HashSet[T]) Union(another *HashSet[T]) *HashSet[T] { | ||
result := NewHashSet[T]() | ||
for item := range hash.items { | ||
result.Add(item) | ||
} | ||
for item := range another.items { | ||
result.Add(item) | ||
} | ||
return result | ||
} | ||
|
||
// Difference returns a new HashSet containing the elements that are in the current set but not in another set. | ||
// Parameters: | ||
// - `another`: Another `HashSet` to compare against. | ||
// | ||
// Returns: | ||
// - A new `HashSet` containing the difference between the current set and the other set. | ||
// | ||
// Example usage: | ||
// | ||
// resultSet := hashSet.Difference(anotherSet) // Returns the difference between two sets. | ||
func (hash *HashSet[T]) Difference(another *HashSet[T]) *HashSet[T] { | ||
result := NewHashSet[T]() | ||
for item := range hash.items { | ||
if _, exist := another.items[item]; !exist { | ||
result.Add(item) | ||
} | ||
} | ||
return result | ||
} | ||
|
||
// Slice converts the HashSet into a slice of elements. | ||
// Returns: | ||
// - A slice containing all elements in the set. | ||
// | ||
// Example usage: | ||
// | ||
// slice := hashSet.Slice() // Converts the set to a slice. | ||
func (hash *HashSet[T]) Slice() []T { | ||
slices := make([]T, hash.Size()) | ||
i := 0 | ||
for val := range hash.items { | ||
slices[i] = val | ||
i++ | ||
} | ||
return slices | ||
} | ||
|
||
// String returns a string representation of the HashSet, with elements separated by commas. | ||
// Returns: | ||
// - A string that represents the elements in the set. | ||
// | ||
// Example usage: | ||
// | ||
// str := hashSet.String() // Returns a string representation of the set. | ||
func (hash *HashSet[T]) String() string { | ||
s := "" | ||
for val := range hash.items { | ||
if IsEmpty(s) { | ||
s = fmt.Sprintf("%v", val) | ||
} else { | ||
s = fmt.Sprintf("%s,%v", s, val) | ||
} | ||
} | ||
return s | ||
} |
Oops, something went wrong.