Documentation
¶
Overview ¶
Package coll provides generic collection types and functional utilities for working with slices and maps in Go.
The package is organised into three layers:
Concrete collection types – HashMap, HashSet, and Stack – each backed by the corresponding standard Go data structure and exposed through a typed, method-based API.
Map utilities – standalone functions for transforming, merging, filtering, flattening, and inverting maps with full type-parameter support.
Slice utilities – higher-order functions such as Map, Filter, Reduce, Chunk, and ZipWith that operate on slices of any element type.
Generic Collection Types ¶
HashMap[K, V comparable] is a typed wrapper around Go's built-in map that provides Put, Get, Remove, ContainsKey, KeySet, and Clear operations:
m := coll.NewHashMap[string, int]()
m.Put("hits", 42)
fmt.Println(m.Get("hits")) // 42
HashSet[T comparable] stores unique elements and supports set-algebra operations including Intersection, Union, and Difference:
s := coll.NewHashSet("a", "b", "c")
s.Add("d")
fmt.Println(s.Contains("b")) // true
Stack[T comparable] implements a last-in, first-out (LIFO) structure with Push, Pop, Peek, and IsEmpty:
stack := coll.NewStack[int]() stack.Push(1) stack.Push(2) fmt.Println(stack.Pop()) // 2
Map Utilities ¶
MergeComp, DeepMerge, FlattenMap, UnflattenMap, PickComp, OmitComp, and InvertComp cover the most common map transformation patterns. Functions whose names end in Comp accept keys constrained to comparable, while their non-Comp counterparts accept map[any]V for looser typing.
Slice Utilities ¶
Map and ToSlice transform each element, ToMap indexes a slice by a key function, and GetOrDefault provides a safe fallback for map lookups.
All functions are safe for concurrent use if the underlying collections are not mutated during the call. The collection types themselves are not goroutine-safe; external synchronisation is required when sharing instances across goroutines.
Index ¶
- func AllMatch[T any](slice []T, predicate func(T) bool) bool
- func AnyMatch[T any](slice []T, predicate func(T) bool) bool
- func AppendIf[T comparable](slice []T, element T) []T
- func Cartesian[T any](slices ...[]T) [][]T
- func Chunk[T any](slice []T, chunkSize int) [][]T
- func Concat[T any](slices ...[]T) []T
- func Contains[T comparable](array []T, item T) bool
- func ContainsKeyComp[K comparable, V any](m map[K]V, key K) bool
- func DeepMerge(dst, src map[string]any) map[string]any
- func Difference[T comparable](slice1, slice2 []T) []T
- func Equal[T comparable](a []T, b []T) bool
- func Filter[T any](list []T, condition func(T) bool) []T
- func FilterMap[K any, V any](m map[any]V, filter func(V) bool) map[any]V
- func FindIndex[T comparable](slice []T, target T) int
- func Flatten[T any](s []any) []T
- func FlattenDeep(arr any) []any
- func FlattenMap(m map[string]any, prefix string) map[string]any
- func GetOrDefault[K comparable, V any](m map[K]V, key K, defaultValue V) V
- func GroupBy[T any, K comparable](slice []T, getKey func(T) K) map[K][]T
- func HasKey[K comparable, V any](m map[K]V, key K) bool
- func IndexExists[T any](slice []T, index int) bool
- func IndexOf[T comparable](slice []T, item T) int
- func Intersect[T comparable](slice1, slice2 []T) []T
- func InvertComp[K, V comparable](m map[K]V) map[V]K
- func Join[T any](slice []T, separator string) string
- func JoinKeySep[V any](m map[string]V, separator string) string
- func KeyComp[K comparable, V any](m map[K]V) []K
- func Map[T any, U any](list []T, f func(T) U) []U
- func Merge[K any, V any](maps ...map[any]V) map[any]V
- func MergeComp[K comparable, V any](maps ...map[K]V) map[K]V
- func OmitComp[K comparable, V any](m map[K]V, keys ...K) map[K]V
- func PickComp[K comparable, V any](m map[K]V, keys ...K) map[K]V
- func Pop[T any](slice []T) []T
- func Push[T any](slice []T, element T) []T
- func Reduce[T any, U any](slice []T, accumulator func(U, T) U, initialValue U) U
- func ReverseN[T any](slice []T) []T
- func Shift[T any](slice []T) []T
- func Shuffle[T any](slice []T) []T
- func Sort[T any](slice []T, comparer func(T, T) bool) []T
- func Sum[T any](slice []T, transformer func(T) float64) float64
- func ToMap[T any, K comparable](slice []T, keyFunc func(T) K) map[K]T
- func ToSlice[T any, U any](slice []T, mapper func(T) U) []U
- func UnflattenMap(m map[string]any, prefix string) map[string]any
- func Unique[T comparable](slice []T) []T
- func Unshift[T any](slice []T, element T) []T
- func Values[K any, V any](m map[any]V) []V
- func ValuesComp[K comparable, V, U any](m map[K]V, fn func(V) U) map[K]U
- type HashMap
- func (hash *HashMap[K, V]) Clear()
- func (hash *HashMap[K, V]) ContainsKey(key K) bool
- func (hash *HashMap[K, V]) Get(key K) (value V)
- func (hash *HashMap[K, V]) IsEmpty() bool
- func (hash *HashMap[K, V]) KeySet() []K
- func (hash *HashMap[K, V]) Put(key K, value V)
- func (hash *HashMap[K, V]) Remove(key K)
- func (hash *HashMap[K, V]) Size() int
- type HashSet
- func (hash *HashSet[T]) Add(element T)
- func (hash *HashSet[T]) AddAll(elements ...T)
- func (hash *HashSet[T]) Clear()
- func (hash *HashSet[T]) Contains(element T) bool
- func (hash *HashSet[T]) Difference(another *HashSet[T]) *HashSet[T]
- func (hash *HashSet[T]) Intersection(another *HashSet[T]) *HashSet[T]
- func (hash *HashSet[T]) IsEmpty() bool
- func (hash *HashSet[T]) Remove(element T)
- func (hash *HashSet[T]) RemoveAll(elements ...T)
- func (hash *HashSet[T]) Size() int
- func (hash *HashSet[T]) Slice() []T
- func (hash *HashSet[T]) String() string
- func (hash *HashSet[T]) Union(another *HashSet[T]) *HashSet[T]
- type Stack
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AllMatch ¶
AllMatch checks if all elements in a slice satisfy a given condition and returns a boolean result.
This function takes an input slice `slice` and a predicate function `predicate`. It iterates over each element in the slice, applying the predicate function to each one. If any element does not satisfy the predicate (i.e., the predicate returns `false`), the function immediately returns `false`. If all elements satisfy the predicate, the function returns `true`.
The function is generic, allowing it to work with slices of any type `T`.
Parameters:
- `slice`: The input slice whose elements will be checked. It can contain elements of any type `T`.
- `predicate`: A function that takes an element of type `T` and returns a boolean. This function represents the condition that each element must satisfy. If the predicate returns `true` for an element, the element meets the condition.
Returns:
- `true` if all elements in the slice satisfy the predicate; `false` if any element does not.
Example:
// Checking if all integers in a slice are positive
numbers := []int{2, 4, 6, 8}
allPositive := AllMatch(numbers, func(n int) bool {
return n > 0
})
// allPositive will be true
// Checking if all strings in a slice have a length greater than 3
words := []string{"apple", "banana", "pear"}
allLong := AllMatch(words, func(s string) bool {
return len(s) > 3
})
// allLong will be true
// If the slice is empty, returns true since no elements violate the predicate
empty := []int{}
allMatchEmpty := AllMatch(empty, func(n int) bool {
return n > 0
})
// allMatchEmpty will be true
func AnyMatch ¶
AnyMatch checks if any element in a slice satisfies a given condition and returns a boolean result.
This function takes an input slice `slice` and a predicate function `predicate`. It iterates over each element in the slice, applying the predicate function to each one. If the predicate returns `true` for any element, the function immediately returns `true`. If no elements satisfy the predicate, the function returns `false`.
The function is generic, allowing it to work with slices of any type `T`.
Parameters:
- `slice`: The input slice whose elements will be checked. It can contain elements of any type `T`.
- `predicate`: A function that takes an element of type `T` and returns a boolean. This function represents the condition that an element must satisfy. If the predicate returns `true` for an element, the element meets the condition.
Returns:
- `true` if at least one element in the slice satisfies the predicate; `false` if no elements do.
Example:
// Checking if any integers in a slice are even
numbers := []int{1, 3, 5, 6}
anyEven := AnyMatch(numbers, func(n int) bool {
return n%2 == 0
})
// anyEven will be true because 6 is even
// Checking if any strings in a slice contain the letter "a"
words := []string{"apple", "banana", "cherry"}
containsA := AnyMatch(words, func(s string) bool {
return strings.Contains(s, "a")
})
// containsA will be true because "apple" and "banana" contain "a"
// Checking an empty slice returns false since no elements satisfy the predicate
empty := []int{}
anyMatchEmpty := AnyMatch(empty, func(n int) bool {
return n > 0
})
// anyMatchEmpty will be false
func AppendIf ¶
func AppendIf[T comparable](slice []T, element T) []T
AppendIf appends an element to a slice if it is not already present.
This function takes an input slice `slice` and an element `element`. It first checks if the element is already in the slice by calling the helper function `ContainsN`. If the element is not found in the slice, the function appends it to the end of the slice. If the element is already present, the original slice is returned unchanged.
The function is generic and requires that the type `T` be `comparable`, allowing the function to use the `==` operator in `ContainsN` to check for equality.
Parameters:
- `slice`: The input slice to which the element might be appended. It can contain elements of any comparable type `T`.
- `element`: The element to be appended if it is not already in `slice`. It is of type `T`.
Returns:
- A new slice of type `[]T` containing the original elements and, if missing, the appended `element`.
Example:
// Adding a missing integer to a slice
numbers := []int{1, 2, 3}
updatedNumbers := AppendIf(numbers, 4)
// updatedNumbers will be []int{1, 2, 3, 4}
// Trying to add an existing integer to a slice
updatedNumbers = AppendIf(numbers, 3)
// updatedNumbers will be []int{1, 2, 3} (unchanged)
// Adding a missing string to a slice
words := []string{"apple", "banana"}
updatedWords := AppendIf(words, "cherry")
// updatedWords will be []string{"apple", "banana", "cherry"}
func Cartesian ¶
func Cartesian[T any](slices ...[]T) [][]T
Cartesian computes the Cartesian product of multiple slices and returns the result as a slice of slices.
This function takes multiple slices of type `[]T` and computes their Cartesian product. The Cartesian product of two or more sets (or slices in this case) is the set of all possible combinations where each combination consists of one element from each slice. The function recursively computes the product of the slices, starting from the second slice and combining it with each element of the first slice. The result is a slice of slices, where each inner slice is a combination of elements from the input slices.
The function is generic, allowing it to work with slices of any type `T`.
Parameters:
- `slices`: A variadic parameter that represents multiple slices to compute the Cartesian product of. Each slice can contain elements of any type `T`.
Returns:
- A slice of slices (`[][]T`), where each inner slice represents a unique combination of elements from the input slices.
Example:
// Cartesian product of two slices of integers
slice1 := []int{1, 2}
slice2 := []int{3, 4}
product := Cartesian(slice1, slice2)
// product will be [][]int{{1, 3}, {1, 4}, {2, 3}, {2, 4}}
// Cartesian product of three slices of strings
slice3 := []string{"a", "b"}
slice4 := []string{"x", "y"}
slice5 := []string{"1", "2"}
productStrings := Cartesian(slice3, slice4, slice5)
// productStrings will be [][]string{
// {"a", "x", "1"}, {"a", "x", "2"},
// {"a", "y", "1"}, {"a", "y", "2"},
// {"b", "x", "1"}, {"b", "x", "2"},
// {"b", "y", "1"}, {"b", "y", "2"}
// }
// Cartesian product of an empty slice returns an empty slice
empty := []int{}
productEmpty := Cartesian(empty)
// productEmpty will be [][]int{{}}
func Chunk ¶
Chunk splits a slice into smaller slices (chunks) of the specified size.
This function takes an input slice `slice` and a `chunkSize` and splits the input slice into smaller slices, each containing up to `chunkSize` elements. The function returns a slice of slices containing the chunked elements. If the `chunkSize` is greater than the length of the input slice, the entire slice will be returned as a single chunk. If the `chunkSize` is less than or equal to 0, the function returns `nil`.
The function is generic, allowing it to work with slices of any type `T`.
Parameters:
- `slice`: The input slice to be split into chunks. It can contain elements of any type `T`.
- `chunkSize`: The size of each chunk. If this value is less than or equal to 0, the function returns `nil`.
Returns:
- A slice of slices (`[][]T`), where each inner slice contains up to `chunkSize` elements from the original slice. If the slice cannot be split into even chunks, the last chunk may contain fewer elements than `chunkSize`.
Example:
// Chunking a slice of integers into chunks of size 2
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
chunks := Chunk(numbers, 2)
// chunks will be [][]int{{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9}}
// Chunking a slice of strings into chunks of size 3
words := []string{"apple", "banana", "cherry", "date", "elderberry", "fig"}
chunksWords := Chunk(words, 3)
// chunksWords will be [][]string{{"apple", "banana", "cherry"}, {"date", "elderberry", "fig"}}
// Chunking an empty slice returns an empty slice of slices
empty := []int{}
chunksEmpty := Chunk(empty, 3)
// chunksEmpty will be [][]int{}
// If chunkSize is 0 or negative, return nil
chunksInvalid := Chunk(numbers, -1)
// chunksInvalid will be nil
func Concat ¶
func Concat[T any](slices ...[]T) []T
Concat returns a new slice that is the result of concatenating multiple input slices into a single slice.
This function takes a variable number of slices as input and combines them into one contiguous slice. It first calculates the total length needed for the resulting slice, then copies each input slice into the appropriate position within the resulting slice.
The function is generic, allowing it to concatenate slices of any type `T`.
Parameters:
- `slices`: A variadic parameter representing the slices to concatenate. Each slice can contain elements of any type `T`, and they will be concatenated in the order they are provided.
Returns:
- A new slice of type `[]T` containing all elements from each input slice in sequence.
Example:
// Concatenating integer slices
a := []int{1, 2}
b := []int{3, 4}
c := []int{5, 6}
combined := Concat(a, b, c)
// combined will be []int{1, 2, 3, 4, 5, 6}
// Concatenating string slices
words1 := []string{"hello", "world"}
words2 := []string{"go", "lang"}
concatenatedWords := Concat(words1, words2)
// concatenatedWords will be []string{"hello", "world", "go", "lang"}
func Contains ¶
func Contains[T comparable](array []T, item T) bool
Contains checks if a specified item is present within a given slice.
This function iterates over a slice of any type that supports comparison and checks if the specified `item` exists within it. It returns `true` if the `item` is found and `false` otherwise.
The function is generic, so it can be used with any comparable type, including strings, integers, floats, or custom types that implement the comparable interface.
Parameters:
- `array`: The slice of elements to search through. This slice can contain any type `T` that supports comparison (e.g., int, string).
- `item`: The item to search for within `array`. It should be of the same type `T` as the elements in `array`.
Returns:
- `true` if `item` is found within `array`, `false` otherwise.
Example:
numbers := []int{1, 2, 3, 4, 5}
isPresent := Contains(numbers, 3) // isPresent will be true as 3 is in the slice
names := []string{"Alice", "Bob", "Charlie"}
isPresent := Contains(names, "Eve") // isPresent will be false as "Eve" is not in the slice
func ContainsKeyComp ¶
func ContainsKeyComp[K comparable, V any](m map[K]V, key K) bool
ContainsKeyComp checks if a specified key is present within a given map.
This function takes a map with keys of any comparable type `K` and values of any type `V`. It checks if the specified `key` exists in the map `m`. If the key is found, it returns `true`; otherwise, it returns `false`.
The function is generic and can be used with maps that have keys of any type that supports comparison (e.g., int, string). The value type `V` can be any type.
Parameters:
- `m`: The map in which to search for the key. The map has keys of type `K` and values of type `V`.
- `key`: The key to search for within `m`. It should be of the same type `K` as the keys in `m`.
Returns:
- `true` if `key` is found in `m`, `false` otherwise.
Example:
ages := map[string]int{"Alice": 30, "Bob": 25}
isPresent := ContainsKeyComp(ages, "Alice") // isPresent will be true as "Alice" is a key in the map
prices := map[int]float64{1: 9.99, 2: 19.99}
isPresent := ContainsKeyComp(prices, 3) // isPresent will be false as 3 is not a key in the map
func DeepMerge ¶
DeepMerge merges two maps, deeply combining values from the source map into the target map.
This function takes two maps: `target` and `source`, both with string keys and interface{} values. It recursively merges the values from the `source` map into the `target` map. If a key exists in both maps, the function checks if the values associated with the key are themselves maps. If so, it recursively merges the nested maps. Otherwise, it directly overwrites the target map's value with the value from the source map. This function allows for deep merging of nested maps.
The function modifies the `target` map in place and does not return anything.
Parameters:
- `target`: The map that will be updated with values from the `source`. It is modified in place.
- `source`: The map whose values will be merged into the `target`.
Example:
// Merging two maps with nested maps
target := map[string]interface{}{
"fruit": map[string]interface{}{"apple": 5, "banana": 10},
"vegetable": map[string]interface{}{"carrot": 3},
}
source := map[string]interface{}{
"fruit": map[string]interface{}{"banana": 7, "orange": 2},
"vegetable": map[string]interface{}{"spinach": 5},
"grain": 100,
}
DeepMerge(target, source)
// target will now be:
// map[string]interface{}{
// "fruit": map[string]interface{}{"apple": 5, "banana": 7, "orange": 2},
// "vegetable": map[string]interface{}{"carrot": 3, "spinach": 5},
// "grain": 100,
// }
// If there is no conflict, the value from the source is added as is.
// If the source value is a nested map, the function will perform a deep merge.
func Difference ¶
func Difference[T comparable](slice1, slice2 []T) []T
Difference returns a new slice containing elements that are unique to each of the two input slices.
This function takes two input slices, `slice1` and `slice2`, and identifies elements that are present in either slice but not both. It creates a map to track the elements of `slice1`, then checks for unique elements in `slice2` by confirming that they are not present in `slice1`. Finally, it appends any unique elements from `slice1` to ensure that the result includes all elements unique to either slice.
The function is generic, allowing it to work with slices of any `comparable` type `T`.
Parameters:
- `slice1`: The first input slice containing elements of any comparable type `T`.
- `slice2`: The second input slice containing elements of any comparable type `T`.
Returns:
- A new slice of type `[]T` that contains elements unique to either `slice1` or `slice2`. If an element appears in both slices, it will not appear in the result.
Example:
// Finding unique integers between two slices
numbers1 := []int{1, 2, 3, 4}
numbers2 := []int{3, 4, 5, 6}
uniqueNumbers := Difference(numbers1, numbers2)
// uniqueNumbers will be []int{1, 2, 5, 6}
// Finding unique strings between two slices
words1 := []string{"apple", "banana", "cherry"}
words2 := []string{"banana", "date"}
uniqueWords := Difference(words1, words2)
// uniqueWords will be []string{"apple", "cherry", "date"}
// Difference with an empty slice results in the original slice
empty := []int{}
uniqueFromEmpty := Difference(numbers1, empty)
// uniqueFromEmpty will be []int{1, 2, 3, 4}
func Equal ¶
func Equal[T comparable](a []T, b []T) bool
Equal checks if two slices are equal in both length and elements.
This function compares two slices `a` and `b` of any comparable type `T`. It first checks if the lengths of the two slices are the same. If they are not, it returns `false`. If the lengths match, it then iterates through each element in `a` and `b` to check if corresponding elements are equal. If all elements are equal, the function returns `true`; otherwise, it returns `false`.
The function is generic and can be used with slices of any comparable type, such as integers, strings, or other types that support equality comparison.
Parameters:
- `a`: The first slice to compare. It should contain elements of a comparable type `T`.
- `b`: The second slice to compare. It should also contain elements of type `T`.
Returns:
- `true` if both slices have the same length and identical elements at each position; `false` otherwise.
Example:
// Comparing integer slices
a := []int{1, 2, 3}
b := []int{1, 2, 3}
isEqual := Equal(a, b)
// isEqual will be true as both slices contain the same elements in the same order
c := []int{1, 2, 4}
isEqual = Equal(a, c)
// isEqual will be false as the elements differ
// Comparing string slices
names1 := []string{"Alice", "Bob"}
names2 := []string{"Alice", "Bob"}
isEqual = Equal(names1, names2)
// isEqual will be true since the slices have identical elements
func Filter ¶
Filter returns a new slice containing only the elements from the input slice that satisfy a specified condition.
This function iterates over each element in the input slice `list` and applies the provided `condition` function to it. If the `condition` function returns `true` for an element, that element is added to the `filtered` slice. At the end, the function returns the `filtered` slice containing only the elements that met the condition.
The function is generic, allowing it to work with slices of any type `T` and any condition function that takes a `T` and returns a boolean.
Parameters:
- `list`: The slice of elements to filter. It can contain elements of any type `T`.
- `condition`: A function that defines the filtering criteria. It takes an element of type `T` as input and returns `true` if the element should be included in the result, or `false` if it should be excluded.
Returns:
- A new slice of type `[]T` containing only the elements from `list` for which the `condition` function returned `true`.
Example:
numbers := []int{1, 2, 3, 4, 5}
oddNumbers := Filter(numbers, func(n int) bool { return n%2 != 0 })
// oddNumbers will be []int{1, 3, 5} as only the odd numbers satisfy the condition
words := []string{"apple", "banana", "cherry"}
longWords := Filter(words, func(word string) bool { return len(word) > 5 })
// longWords will be []string{"banana", "cherry"} as they are longer than 5 characters
func FilterMap ¶
FilterMap filters the key-value pairs of a map based on a condition provided by the filter function.
This function iterates over each key-value pair in the input map `m` and applies the provided `filter` function to the value. If the `filter` function returns `true` for a value, that key-value pair is added to the `filteredMap`. Otherwise, the pair is excluded. The function returns a new map containing only the key-value pairs that satisfy the condition specified in the `filter` function.
The function is generic, allowing it to work with maps where the keys and values can be of any type `K` and `V`, respectively.
Parameters:
- `m`: The input map to be filtered, with keys of type `any` and values of type `V`.
- `filter`: A function that takes a value of type `V` and returns a boolean. It determines whether the corresponding key-value pair should be included in the result map.
Returns:
- A new map of type `map[any]V`, containing only the key-value pairs for which the `filter` function returned `true`.
Example:
// Filtering a map of integers, keeping only values greater than 10
map1 := map[any]int{"a": 5, "b": 15, "c": 20}
filtered := FilterMap(map1, func(v int) bool {
return v > 10
})
// filtered will be map[any]int{"b": 15, "c": 20}
// Filtering a map of strings, keeping only values with length greater than 3
map2 := map[any]string{"a": "apple", "b": "banana", "c": "cat"}
filteredStrings := FilterMap(map2, func(v string) bool {
return len(v) > 3
})
// filteredStrings will be map[any]string{"a": "apple", "b": "banana"}
// Filtering an empty map returns an empty map
emptyMap := map[any]int{}
filteredEmpty := FilterMap(emptyMap, func(v int) bool {
return v > 10
})
// filteredEmpty will be an empty map
func FindIndex ¶
func FindIndex[T comparable](slice []T, target T) int
FindIndex searches for the first occurrence of a target element in a slice and returns its index. If the element is not found, it returns -1.
This function iterates over each element in the input slice `slice` and compares each element to the specified `target`. When the first occurrence of `target` is found, the function returns the index of that element. If the element is not found, the function returns -1 to indicate that the target is not present in the slice.
The function is generic, allowing it to work with slices of any comparable type `T`, such as integers, strings, or other types that support equality comparison.
Parameters:
- `slice`: The input slice in which to search for the target element. It can contain elements of any comparable type `T`.
- `target`: The element to search for within the slice. It should be of the same type `T` as the elements in `slice`.
Returns:
- The zero-based index of the first occurrence of `target` in the slice if it exists; otherwise, -1 if the target is not found.
Example:
// Searching for an integer in a slice
numbers := []int{1, 2, 3, 4}
index := FindIndex(numbers, 3)
// index will be 2, as 3 is located at index 2 in the slice
// Searching for a string in a slice
words := []string{"apple", "banana", "cherry"}
index = FindIndex(words, "banana")
// index will be 1, as "banana" is at index 1 in the slice
// Item not found in the slice
index = FindIndex(words, "date")
// index will be -1, as "date" is not in the slice
func Flatten ¶
Flatten takes a slice of potentially nested elements and returns a new slice containing all elements of type `T` in a flat structure.
This function recursively processes each element in the input slice `s`, checking if it is a nested slice (`[]interface{}`). If a nested slice is found, `Flatten` is called recursively to flatten it and append its elements to the `result` slice. If an element is of type `T`, it is directly appended to `result`. Elements that are neither `[]interface{}` nor of type `T` are ignored.
The function is generic, allowing it to work with any element type `T`, which must be specified when calling the function. This makes `Flatten` useful for flattening slices with nested structures while filtering only the elements of a specified type.
Parameters:
- `s`: A slice of `interface{}`, which can contain nested slices (`[]interface{}`) or elements of any type. Nested slices may contain more nested slices at arbitrary depths.
Returns:
- A new slice of type `[]T` containing all elements of type `T` from `s`, flattened into a single level.
Example:
// Flattening a nested slice of integers
nestedInts := []interface{}{1, []interface{}{2, 3}, []interface{}{[]interface{}{4, 5}}}
flatInts := Flatten[int](nestedInts)
// flatInts will be []int{1, 2, 3, 4, 5}
// Flattening a nested slice with mixed types, extracting only strings
mixedNested := []interface{}{"apple", []interface{}{"banana", 1, []interface{}{"cherry"}}}
flatStrings := Flatten[string](mixedNested)
// flatStrings will be []string{"apple", "banana", "cherry"}
// Flattening an empty slice
empty := []interface{}{}
flatEmpty := Flatten[int](empty)
// flatEmpty will be []int{}
func FlattenDeep ¶
FlattenDeep takes a nested structure of arbitrary depth and returns a flat slice containing all elements in a single level.
This function recursively processes each element in `arr`. If an element is itself a slice (`[]interface{}`), `FlattenDeep` calls itself to flatten that nested slice and appends its elements to the `result` slice. If the element is not a slice, it is directly added to `result`. The function allows flattening of complex nested structures while maintaining all elements in a single-level output.
This function operates with values of type `interface{}`, making it flexible enough to handle mixed types in the input. It returns a slice of `interface{}`, which may contain elements of varying types from the original nested structure.
Parameters:
- `arr`: The input slice, which can contain nested slices of arbitrary depth and elements of any type.
Returns:
- A slice of `[]interface{}` containing all elements from `arr` flattened into a single level.
Example:
// Flattening a nested structure of mixed values
nested := []interface{}{1, []interface{}{2, 3, []interface{}{4, []interface{}{5}}}}
flat := FlattenDeep(nested)
// flat will be []interface{}{1, 2, 3, 4, 5}
// Flattening a deeply nested structure with varied types
mixedNested := []interface{}{"apple", []interface{}{"banana", 1, []interface{}{"cherry"}}}
flatMixed := FlattenDeep(mixedNested)
// flatMixed will be []interface{}{"apple", "banana", 1, "cherry"}
// Flattening a non-nested input returns the input as-is
nonNested := 5
flatNonNested := FlattenDeep(nonNested)
// flatNonNested will be []interface{}{5}
func FlattenMap ¶
FlattenMap flattens a nested map into a single-level map with dot-separated keys.
This function takes a nested map `m` where the keys are strings and the values can be either primitive values or other nested maps. It recursively traverses the nested structure, constructing new keys by concatenating parent keys with child keys using a dot (".") as a separator.
The function returns a new map where all nested keys are flattened into a single level, with the keys representing the path to each value in the original nested map.
Parameters:
- `m`: The nested map to be flattened. It has string keys and values of type `any`.
- `prefix`: A string prefix used to build the keys during recursion. This is typically an empty string when the function is called initially.
Returns:
- A new map of type `map[string]any`, where all nested keys from the input map `m` are flattened into a single level with dot-separated keys.
Example:
nestedMap := map[string]any{
"user": map[string]any{
"name": "Alice",
"address": map[string]any{
"city": "Wonderland",
"zip": "12345",
},
},
"age": 30,
}
flattened := FlattenMap(nestedMap, "")
// flattened will be:
// map[string]any{
// "user.name": "Alice",
// "user.address.city": "Wonderland",
// "user.address.zip": "12345",
// "age": 30,
// }
func GetOrDefault ¶
func GetOrDefault[K comparable, V any](m map[K]V, key K, defaultValue V) V
GetOrDefault retrieves the value for a given key from the map.
This function checks if the specified `key` exists in the map `m`. If the key is found, it returns the corresponding value. If the key is not found, it returns the provided `defaultValue`.
The function is generic, allowing it to work with maps where the keys are of any comparable type `K` and the values are of any type `V`.
Parameters:
- `m`: The map from which to retrieve the value. It has keys of type `K` and values of type `V`.
- `key`: The key to look for in the map. It should be of the same type `K` as the keys in `m`.
- `defaultValue`: The value to return if the key is not found in the map.
Returns:
- The value associated with the specified `key` if it exists in the map `m`.
- The `defaultValue` if the key is not found.
Example:
// Retrieving a value from a map with a default fallback
m := map[string]int{"a": 1, "b": 2, "c": 3}
value := GetOrDefault(m, "b", 0)
// value will be 2 as "b" exists in the map
func GroupBy ¶
func GroupBy[T any, K comparable](slice []T, getKey func(T) K) map[K][]T
GroupBy groups elements of a slice into a map based on a specified key.
This function iterates over each element in the input slice `slice`, applies the provided `getKey` function to extract a key for each element, and groups elements that share the same key into a slice. The function then returns a map where each key maps to a slice of elements that correspond to that key.
The function is generic, allowing it to work with slices of any type `T` and to generate keys of any comparable type `K`. This makes `GroupBy` useful for organizing data based on shared attributes, such as grouping items by category or organizing records by a specific field.
Parameters:
- `slice`: The input slice containing elements to be grouped. It can be of any type `T`.
- `getKey`: A function that takes an element of type `T` and returns a key of type `K`, which is used to group the element in the resulting map.
Returns:
- A map of type `map[K][]T`, where each key is associated with a slice of elements that share that key.
Example:
// Grouping integers by even and odd
numbers := []int{1, 2, 3, 4, 5}
grouped := GroupBy(numbers, func(n int) string {
if n%2 == 0 {
return "even"
}
return "odd"
})
// grouped will be map[string][]int{"even": {2, 4}, "odd": {1, 3, 5}}
// Grouping people by age
type Person struct {
Name string
Age int
}
people := []Person{{Name: "Alice", Age: 30}, {Name: "Bob", Age: 25}, {Name: "Charlie", Age: 30}}
groupedByAge := GroupBy(people, func(p Person) int { return p.Age })
// groupedByAge will be map[int][]Person{30: {{Name: "Alice", Age: 30}, {Name: "Charlie", Age: 30}}, 25: {{Name: "Bob", Age: 25}}}
// Grouping strings by their length
words := []string{"apple", "pear", "banana", "peach"}
groupedByLength := GroupBy(words, func(word string) int { return len(word) })
// groupedByLength will be map[int][]string{5: {"apple", "peach"}, 4: {"pear"}, 6: {"banana"}}
func HasKey ¶
func HasKey[K comparable, V any](m map[K]V, key K) bool
HasKey checks if a specified key is present within a given map.
This function takes a map with keys of any comparable type `K` and values of any type `V`. It checks if the specified `key` exists in the map `m`. If the key is found, it returns `true`; otherwise, it returns `false`.
The function is generic and can be used with maps that have keys of any type that supports comparison (e.g., int, string). The value type `V` can be any type.
Parameters:
- `m`: The map in which to search for the key. The map has keys of type `K` and values of type `V`.
- `key`: The key to search for within `m`. It should be of the same type `K` as the keys in `m`.
Returns:
- `true` if `key` is found in `m`, `false` otherwise.
Example:
ages := map[string]int{"Alice": 30, "Bob": 25}
isPresent := HasKey(ages, "Alice") // isPresent will be true as "Alice" is a key in the map
prices := map[int]float64{1: 9.99, 2: 19.99}
isPresent := HasKey(prices, 3) // isPresent will be false as 3 is not a key in the map
func IndexExists ¶
IndexExists checks whether a given index is valid for the provided slice.
This function takes a slice `slice` of any type `T` and an integer `index`, and returns a boolean indicating whether the specified index is within the valid range for the slice. A valid index is one that is greater than or equal to 0 and less than the length of the slice.
Parameters:
- `slice`: The input slice of any type `T` that is being checked.
- `index`: The index to check for validity in the slice.
Returns:
- `true` if the index is within the bounds of the slice (i.e., 0 <= index < len(slice)).
- `false` otherwise, such as when the index is negative or greater than or equal to the length of the slice.
Example:
// Checking if an index exists in a slice
numbers := []int{1, 2, 3, 4}
exists := IndexExists(numbers, 2)
// exists will be true, as index 2 is valid for the slice
// Checking an invalid index
exists = IndexExists(numbers, 5)
// exists will be false, as index 5 is out of bounds for the slice
func IndexOf ¶
func IndexOf[T comparable](slice []T, item T) int
IndexOf searches for a specific element in a slice and returns its index if found.
This function iterates over each element in the input slice `slice` to find the first occurrence of the specified `item`. If `item` is found, the function returns the index of `item` within `slice`. If `item` is not present in the slice, it returns -1.
The function is generic, allowing it to operate on slices of any comparable type `T` (e.g., int, string, or other types that support equality comparison).
Parameters:
- `slice`: The slice in which to search for `item`. It can contain elements of any comparable type `T`.
- `item`: The item to search for within `slice`. It should be of the same type `T` as the elements in `slice`.
Returns:
- The zero-based index of `item` in `slice` if it exists; otherwise, -1.
Example:
// Searching for an integer in a slice
numbers := []int{1, 2, 3, 4}
index := IndexOf(numbers, 3)
// index will be 2, as 3 is located at index 2 in the slice
// Searching for a string in a slice
words := []string{"apple", "banana", "cherry"}
index = IndexOf(words, "banana")
// index will be 1, as "banana" is at index 1 in the slice
// Item not found in the slice
index = IndexOf(words, "date")
// index will be -1, as "date" is not in the slice
func Intersect ¶
func Intersect[T comparable](slice1, slice2 []T) []T
Intersect returns a new slice containing elements that are present in both input slices.
This function takes two input slices, `slice1` and `slice2`, and identifies elements that are present in both slices. It uses a map to track the elements of `slice1`, then iterates over `slice2` to find common elements. If an element from `slice2` is found in the map (indicating it exists in `slice1`), it is added to the result slice.
The function is generic, allowing it to work with slices of any `comparable` type `T`.
Parameters:
- `slice1`: The first input slice containing elements of any comparable type `T`.
- `slice2`: The second input slice containing elements of any comparable type `T`.
Returns:
- A new slice of type `[]T` that contains the elements found in both `slice1` and `slice2`. Each element in the result slice will appear only once, even if it is duplicated in the input slices.
Example:
// Finding common integers between two slices
numbers1 := []int{1, 2, 3, 4}
numbers2 := []int{3, 4, 5, 6}
commonNumbers := Intersect(numbers1, numbers2)
// commonNumbers will be []int{3, 4}
// Finding common strings between two slices
words1 := []string{"apple", "banana", "cherry"}
words2 := []string{"banana", "cherry", "date"}
commonWords := Intersect(words1, words2)
// commonWords will be []string{"banana", "cherry"}
// Intersecting with an empty slice results in an empty slice
empty := []int{}
intersectEmpty := Intersect(numbers1, empty)
// intersectEmpty will be []int{}
func InvertComp ¶
func InvertComp[K, V comparable](m map[K]V) map[V]K
InvertComp inverts the keys and values of a map.
This function takes an input map `m` with keys of type `K` and values of type `V`, and creates a new map where the keys and values are swapped. It iterates over each key-value pair in the input map and adds an entry to the `result` map with the value as the key and the key as the value.
The function is generic, allowing it to work with maps where both the keys and values are of any comparable type.
Parameters:
- `m`: The input map to be inverted, with keys of type `K` and values of type `V`.
Returns:
- A new map of type `map[V]K`, where the keys and values from the input map `m` are swapped.
Example:
// Inverting a map with string keys and integer values
m := map[string]int{"a": 1, "b": 2, "c": 3}
inverted := InvertComp(m)
// inverted will be map[int]string{1: "a", 2: "b", 3: "c"}
func Join ¶
Join concatenates the string representation of each element in a slice into a single string, with a specified separator between each element.
This function iterates over each element in the input slice `slice`, converts each element to a string using `fmt.Sprintf` with the `%v` format, and appends it to the `result` string. A separator string `separator` is inserted between elements in the final concatenated result. If the slice has only one element, no separator is added. The function is generic and can work with slices containing elements of any type `T`.
Parameters:
- `slice`: The input slice containing elements to be joined. It can contain elements of any type `T`.
- `separator`: A string that will be inserted between each element in the final result.
Returns:
- A single string that is the result of concatenating all elements in `slice` with the specified `separator` in between.
Example:
// Joining integers with a comma separator
numbers := []int{1, 2, 3}
joinedNumbers := Join(numbers, ", ")
// joinedNumbers will be "1, 2, 3"
// Joining strings with a space separator
words := []string{"Go", "is", "awesome"}
joinedWords := Join(words, " ")
// joinedWords will be "Go is awesome"
// Joining an empty slice returns an empty string
emptySlice := []int{}
joinedEmpty := Join(emptySlice, ",")
// joinedEmpty will be ""
func JoinKeySep ¶
JoinKeySep concatenates the keys of a map into a single string, with each key separated by a specified separator.
This function takes a map `m` with string keys and any type of values `V`, and a `separator` string. It collects all the keys of the map into a slice, then joins them into a single string using the provided separator.
This function is generic, allowing it to work with maps that have values of any type `V`.
Parameters:
- `m`: A map with string keys and values of any type `V`. Only the keys are used for concatenation.
- `separator`: A string used to separate each key in the resulting string.
Returns:
- A string containing all the keys in the map `m`, separated by the specified `separator`. If the map has no keys, an empty string is returned.
Example:
// Concatenating the keys of a map with a comma separator
m := map[string]int{"apple": 1, "banana": 2, "cherry": 3}
joinedKeys := JoinKeySep(m, ", ")
// joinedKeys will be "apple, banana, cherry"
// Using a different separator
m = map[string]bool{"cat": true, "dog": true}
joinedKeys = JoinKeySep(m, " | ")
// joinedKeys will be "cat | dog"
// With an empty map
emptyMap := map[string]int{}
joinedKeys = JoinKeySep(emptyMap, ",")
// joinedKeys will be ""
func KeyComp ¶
func KeyComp[K comparable, V any](m map[K]V) []K
KeyComp returns all keys of a map.
This function takes a map `m` with keys of type `K` and values of type `V`, and creates a new slice containing all the keys from the map. The function iterates over the map and appends each key to the `keys` slice. The resulting slice will have the same number of elements as the map has key-value pairs, and the order of keys will correspond to the order in which they were iterated over (which is not guaranteed to be in any particular order).
The function is generic, allowing it to work with maps of any key type `K` and value type `V`.
Parameters:
- `m`: The input map from which to extract the keys. The keys are of type `K`
Returns:
- A slice of type `[]K` containing all the keys from the map `m`.
Example:
// Extracting keys from a map of strings to integers
map1 := map[string]int{"a": 1, "b": 2, "c": 3}
keys := KeyComp(map1)
// keys will be []string{"a", "b", "c"}
func Map ¶
Map returns a new slice where each element is the result of applying a specified transformation function to each element in the input slice.
This function iterates over each element in the input slice `list`, applies the provided transformation function `f` to it, and stores the result in the new slice `result`. The length of the resulting slice is the same as the input slice, and each element in `result` corresponds to a transformed element from `list`.
The function is generic, allowing it to work with slices of any type `T` and apply a transformation function that converts each element of type `T` to a new type `U`.
Parameters:
- `list`: The slice of elements to transform. It can contain elements of any type `T`.
- `f`: A function that defines the transformation. It takes an element of type `T` as input and returns a transformed value of type `U`.
Returns:
- A new slice of type `[]U` where each element is the result of applying `f` to the corresponding element in `list`.
Example:
numbers := []int{1, 2, 3, 4, 5}
squaredNumbers := Map(numbers, func(n int) int { return n * n })
// squaredNumbers will be []int{1, 4, 9, 16, 25} as each number is squared
words := []string{"apple", "banana", "cherry"}
wordLengths := Map(words, func(word string) int { return len(word) })
// wordLengths will be []int{5, 6, 6} as each word's length is calculated
func Merge ¶
Merge combines multiple maps into a single map. If there are any key conflicts, the value from the last map will be used.
This function accepts a variable number of maps of type `map[interface{}]V` and merges them into a single map. It iterates through each input map, adding all key-value pairs to the `mergedMap`. If a key already exists in `mergedMap`, the corresponding value from the current map will overwrite the existing value. The function returns the merged map.
The function is generic, allowing it to work with maps where the key is of any type `K` and the value is of any type `V`. It uses `interface{}` as the key type, enabling it to handle a variety of key types, though this may require careful handling of the key types to ensure they are comparable if needed.
Parameters:
- `maps`: A variadic parameter representing multiple maps to be merged. Each map has keys of type `interface{}` and values of type `V`.
Returns:
- A new map of type `map[interface{}]V` containing the merged key-value pairs. If there are key conflicts, the last map's value will be used.
Example:
// Merging two maps with integer keys and string values
map1 := map[interface{}]string{"a": "apple", "b": "banana"}
map2 := map[interface{}]string{"b": "blueberry", "c": "cherry"}
merged := Merge(map1, map2)
// merged will be map[interface{}]string{"a": "apple", "b": "blueberry", "c": "cherry"}
// Merging maps with different value types (e.g., int and string)
map3 := map[interface{}]int{"x": 10, "y": 20}
map4 := map[interface{}]string{"y": "yellow", "z": "zebra"}
mergedMixed := Merge(map3, map4)
// mergedMixed will be map[interface{}]string{"x": "10", "y": "yellow", "z": "zebra"}
// Merging an empty slice of maps returns an empty map
mergedEmpty := Merge()
// mergedEmpty will be an empty map
func MergeComp ¶
func MergeComp[K comparable, V any](maps ...map[K]V) map[K]V
MergeComp merges multiple maps into a new map. Later maps override earlier ones for duplicate keys.
This function takes a variable number of maps with keys of type `K` and values of type `V`, and merges them into a single resulting map. It iterates through each input map, adding all key-value pairs to the `result` map. If a key already exists in `result`, the corresponding value from the current map will overwrite the existing value.
The function is generic, allowing it to work with maps where the keys are of any comparable type `K` and the values are of any type `V`.
Parameters:
- `maps`: A variadic parameter representing multiple maps to be merged. Each map has keys of type `K` and values of type `V`.
Returns:
A new map of type `map[K]V` containing the merged key-value pairs. If there are
key conflicts, the last map's value will be used.
Example:
// Merging two maps with string keys and integer values
map1 := map[string]int{"a": 1, "b": 2}
map2 := map[string]int{"b": 3, "c": 4}
merged := MergeComp(map1, map2)
// merged will be map[string]int{"a": 1, "b": 3, "c": 4}
func OmitComp ¶
func OmitComp[K comparable, V any](m map[K]V, keys ...K) map[K]V
OmitComp creates a new map by excluding specific keys from the input map.
This function takes an input map `m` with keys of type `K` and values of type `V`, along with a variadic list of keys to exclude. It first constructs a set of keys to omit, then iterates over the input map and adds key-value pairs to the `result` map only if the key is not in the omit set. The function returns a new map containing only the key-value pairs that are not excluded.
The function is generic, allowing it to work with maps where the keys are of any comparable type `K` and the values are of any type `V`.
Parameters:
- `m`: The input map from which to exclude key-value pairs. It has keys of type `K` and values of type `V`.
- `keys`: A variadic parameter representing the keys to exclude from the input map.
Returns:
- A new map of type `map[K]V` containing only the key-value pairs that are not excluded.
Example:
// Excluding specific keys from a map with string keys and integer values
m := map[string]int{"a": 1, "b": 2, "c": 3, "d": 4}
omitted := OmitComp(m, "b", "d")
// omitted will be map[string]int{"a": 1, "c": 3}
func PickComp ¶
func PickComp[K comparable, V any](m map[K]V, keys ...K) map[K]V
PickComp creates a new map by selecting specific keys from the input map.
This function takes an input map `m` with keys of type `K` and values of type `V`, along with a variadic list of keys to select. It iterates over the provided keys and checks if each key exists in the input map. If a key is found, it adds the corresponding key-value pair to the `result` map. The function returns a new map containing only the selected key-value pairs.
The function is generic, allowing it to work with maps where the keys are of any comparable type `K` and the values are of any type `V`.
Parameters:
- `m`: The input map from which to select key-value pairs. It has keys of type `K` and values of type `V`.
- `keys`: A variadic parameter representing the keys to select from the input map.
Returns:
- A new map of type `map[K]V` containing only the key-value pairs for the specified keys.
Example:
// Selecting specific keys from a map with string keys and integer values
m := map[string]int{"a": 1, "b": 2, "c": 3, "d": 4}
selected := PickComp(m, "b", "d")
// selected will be map[string]int{"b": 2, "d": 4}
func Pop ¶
func Pop[T any](slice []T) []T
Pop removes the last element from a slice and returns the resulting slice.
This function takes an input slice `slice` and removes its last element by creating a new slice that excludes the last element. The function uses slicing to return a portion of the original slice that ends before the last element. If the input slice is empty, calling this function will result in a runtime panic.
The function is generic, allowing it to work with slices of any type `T`.
Parameters:
- `slice`: The input slice from which the last element will be removed. It can contain elements of any type `T`.
Returns:
- A new slice of type `[]T`, containing all elements from the original slice except the last one.
Example:
// Removing the last element from a slice of integers
numbers := []int{1, 2, 3, 4}
updatedNumbers := Pop(numbers)
// updatedNumbers will be []int{1, 2, 3}
// Removing the last element from a slice of strings
words := []string{"apple", "banana", "cherry"}
updatedWords := Pop(words)
// updatedWords will be []string{"apple", "banana"}
// Attempting to pop from an empty slice will cause a runtime panic
var emptySlice []int
// updatedEmpty := Pop(emptySlice) // This will panic
func Push ¶
func Push[T any](slice []T, element T) []T
Push appends an element to the end of a slice and returns the resulting slice.
This function takes an input slice `slice` and an element `element`, and appends the element to the end of the slice using the built-in `append` function. The function returns a new slice containing the original elements followed by the new element. This function is useful for adding elements dynamically to a slice.
The function is generic, allowing it to work with slices of any type `T`.
Parameters:
- `slice`: The input slice to which the element will be appended. It can contain elements of any type `T`.
- `element`: The element to be appended to the end of the slice. It is of type `T`.
Returns:
- A new slice of type `[]T`, containing the original elements in `slice` with `element` appended at the end.
Example:
// Appending an integer to a slice of integers
numbers := []int{1, 2, 3}
updatedNumbers := Push(numbers, 4)
// updatedNumbers will be []int{1, 2, 3, 4}
// Appending a string to a slice of strings
words := []string{"apple", "banana"}
updatedWords := Push(words, "cherry")
// updatedWords will be []string{"apple", "banana", "cherry"}
// Appending to an empty slice
var emptySlice []int
newSlice := Push(emptySlice, 1)
// newSlice will be []int{1}
func Reduce ¶
Reduce applies an accumulator function over a slice, producing a single accumulated result.
This function iterates over each element in the input slice `slice`, applying the `accumulator` function to combine each element with an accumulated result. It starts with an initial value `initialValue` and successively updates the result by applying `accumulator` to each element in `slice`. The final accumulated result is returned once all elements have been processed.
The function is generic, allowing it to operate on slices of any type `T` and produce an output of any type `U`. This enables flexible aggregation operations such as summing, counting, or accumulating data into more complex structures.
Parameters:
- `slice`: The slice of elements to reduce. It can contain elements of any type `T`.
- `accumulator`: A function that takes the current accumulated result of type `U` and an element of type `T`, then returns the updated accumulated result of type `U`.
- `initialValue`: The initial value for the accumulator, of type `U`. This is the starting point for the reduction process.
Returns:
- The final accumulated result of type `U` after applying `accumulator` to each element in `slice`.
Example:
// Summing integer values in a slice
numbers := []int{1, 2, 3, 4}
sum := Reduce(numbers, func(acc, n int) int { return acc + n }, 0)
// sum will be 10 as each integer is added to the accumulated result
// Concatenating strings in a slice
words := []string{"go", "is", "fun"}
sentence := Reduce(words, func(acc, word string) string { return acc + " " + word }, "")
// sentence will be " go is fun" (note leading space due to initial value being "")
// Using a custom struct and custom accumulator
type Product struct {
Name string
Price float64
}
products := []Product{{Name: "apple", Price: 0.99}, {Name: "banana", Price: 1.29}}
totalPrice := Reduce(products, func(total float64, p Product) float64 { return total + p.Price }, 0.0)
// totalPrice will be 2.28 as each product's price is added to the accumulated total
func ReverseN ¶
func ReverseN[T any](slice []T) []T
ReverseN reverses the order of elements in the input slice and returns a new slice containing the elements in reverse order.
This function creates a new slice `reversed` with the same length as the input slice `slice`. It then uses a two-pointer approach to swap the elements of `slice` from both ends toward the center, effectively reversing the slice. The result is a new slice with elements in the opposite order.
The function is generic, allowing it to work with slices of any type `T`.
Parameters:
- `slice`: The input slice whose elements are to be reversed. It can contain elements of any type `T`.
Returns:
- A new slice of type `[]T` containing the elements of `slice` in reverse order.
Example:
// Reversing a slice of integers
numbers := []int{1, 2, 3, 4}
reversedNumbers := ReverseN(numbers)
// reversedNumbers will be []int{4, 3, 2, 1}
// Reversing a slice of strings
words := []string{"apple", "banana", "cherry"}
reversedWords := ReverseN(words)
// reversedWords will be []string{"cherry", "banana", "apple"}
// Reversing an empty slice returns an empty slice
empty := []int{}
reversedEmpty := ReverseN(empty)
// reversedEmpty will be []int{}
func Shift ¶
func Shift[T any](slice []T) []T
Shift removes the first element from a slice and returns the resulting slice.
This function takes an input slice `slice` and removes its first element by creating a new slice that starts from the second element of the original slice. The function achieves this using slicing, effectively returning a view of the original slice that excludes the first element. If the input slice is empty, calling this function will result in a runtime panic due to out-of-bounds access.
The function is generic, allowing it to work with slices of any type `T`.
Parameters:
- `slice`: The input slice from which the first element will be removed. It can contain elements of any type `T`.
Returns:
- A new slice of type `[]T`, containing all elements from the original slice except the first one.
Example:
// Removing the first element from a slice of integers
numbers := []int{1, 2, 3, 4}
updatedNumbers := Shift(numbers)
// updatedNumbers will be []int{2, 3, 4}
// Removing the first element from a slice of strings
words := []string{"apple", "banana", "cherry"}
updatedWords := Shift(words)
// updatedWords will be []string{"banana", "cherry"}
func Shuffle ¶
func Shuffle[T any](slice []T) []T
Shuffle randomly shuffles the elements of a slice and returns a new slice with the shuffled elements.
This function takes an input slice `slice` and shuffles its elements using a random permutation. It creates a new slice `shuffledSlice` and populates it by selecting elements from the original slice according to a random permutation of indices. The resulting `shuffledSlice` contains the same elements as the input slice, but in a random order. The function uses a seeded random generator to ensure different results each time it is called.
The function is generic, allowing it to work with slices of any type `T`.
Parameters:
- `slice`: The input slice to be shuffled. It can contain elements of any type `T`.
Returns:
- A new slice of type `[]T`, containing the shuffled elements of the input slice.
Example:
// Shuffling a slice of integers
numbers := []int{1, 2, 3, 4, 5}
shuffledNumbers := Shuffle(numbers)
// shuffledNumbers will be a random permutation of [1, 2, 3, 4, 5]
// Shuffling a slice of strings
words := []string{"apple", "banana", "cherry"}
shuffledWords := Shuffle(words)
// shuffledWords will be a random permutation of ["apple", "banana", "cherry"]
// Shuffling an empty slice returns an empty slice
empty := []int{}
shuffledEmpty := Shuffle(empty)
// shuffledEmpty will be []int{}
func Sort ¶
Sort sorts a slice based on a custom comparison function and returns a new sorted slice.
This function takes an input slice `slice` and a comparison function `comparer` that defines the sorting order. The comparison function takes two elements of type `T` and returns `true` if the first element should come before the second one (i.e., if it should be sorted earlier). The function creates a new slice `sortedSlice` by copying the elements of the original slice, then sorts it in place using the provided `comparer`. The resulting `sortedSlice` will be a new slice containing the elements from the original slice, arranged in the order specified by the comparison function.
The function is generic, allowing it to work with slices of any type `T`.
Parameters:
- `slice`: The input slice to be sorted. It can contain elements of any type `T`.
- `comparer`: A comparison function that takes two elements of type `T` and returns a boolean value. It determines the order of the elements: it should return `true` if the first element should come before the second element in the sorted order.
Returns:
- A new slice of type `[]T`, containing the elements from the original slice sorted according to the provided comparison function.
Example:
// Sorting a slice of integers in ascending order
numbers := []int{5, 3, 8, 1, 2}
sortedNumbers := Sort(numbers, func(a, b int) bool {
return a < b
})
// sortedNumbers will be []int{1, 2, 3, 5, 8}
// Sorting a slice of strings in descending order
words := []string{"apple", "banana", "cherry"}
sortedWords := Sort(words, func(a, b string) bool {
return a > b
})
// sortedWords will be []string{"cherry", "banana", "apple"}
// Sorting an empty slice returns an empty slice
empty := []int{}
sortedEmpty := Sort(empty, func(a, b int) bool {
return a < b
})
// sortedEmpty will be []int{}
func Sum ¶
Sum calculates the sum of elements in a slice after transforming each element to a float64.
This function iterates over each element in the input slice `slice`, applies a transformation function `transformer` to convert the element to a float64, and adds the result to a running total. The final sum is returned as a float64.
The function is generic, allowing it to operate on slices of any type `T`. The `transformer` function is used to convert each element to a float64, enabling flexible summation of different types (e.g., integers, custom types with numeric properties).
Parameters:
- `slice`: The slice of elements to sum. It can contain elements of any type `T`.
- `transformer`: A function that takes an element of type `T` and returns a float64 representation, which will be used in the summation.
Returns:
- A float64 representing the sum of the transformed elements.
Example:
// Summing integer slice values
numbers := []int{1, 2, 3, 4}
total := Sum(numbers, func(n int) float64 { return float64(n) })
// total will be 10.0 as each integer is converted to float64 and summed
// Summing custom struct values
type Product struct {
Price float64
}
products := []Product{{Price: 9.99}, {Price: 19.99}, {Price: 5.0}}
totalPrice := Sum(products, func(p Product) float64 { return p.Price })
// totalPrice will be 34.98 as the prices are summed
func ToMap ¶
func ToMap[T any, K comparable](slice []T, keyFunc func(T) K) map[K]T
ToMap converts a slice into a map, using a specified function to generate keys for each element in the slice.
This function iterates over each element in the input slice `slice`, applies the provided `keyFunc` function to generate a key for each element, and then inserts the element into the resulting map `result` using that key. This allows the creation of a map from a slice, where each element is accessible via a unique key.
The function is generic, allowing it to operate on slices of any type `T` and generate keys of any comparable type `K`. The resulting map will have keys of type `K` and values of type `T`.
Parameters:
- `slice`: The slice of elements to convert to a map. It can contain elements of any type `T`.
- `keyFunc`: A function that takes an element of type `T` and returns a key of type `K`, which is used as the key for each element in the resulting map.
Returns:
- A map of type `map[K]T`, where each element in `slice` is inserted using the key generated by `keyFunc`. If `keyFunc` generates the same key for multiple elements, the last one will overwrite the previous entry in the map.
Example:
// Converting a slice of strings to a map with string lengths as keys
words := []string{"apple", "banana", "cherry"}
wordMap := ToMap(words, func(word string) int { return len(word) })
// wordMap will be map[int]string{5: "apple", 6: "cherry"}
// Note: "banana" is overwritten by "cherry" as they have the same key 6
// Converting a slice of structs to a map using a struct field as the key
type Person struct {
ID int
Name string
}
people := []Person{{ID: 1, Name: "Alice"}, {ID: 2, Name: "Bob"}}
personMap := ToMap(people, func(p Person) int { return p.ID })
// personMap will be map[int]Person{1: {ID: 1, Name: "Alice"}, 2: {ID: 2, Name: "Bob"}}
func ToSlice ¶
ToSlice applies a mapping function to each element in the input slice and returns a new slice containing the results of the mapping.
This function iterates over each element in the input slice `slice` and applies the provided `mapper` function to each element. The result of applying the mapping function to each element is stored in a new slice `mappedSlice`. This allows for transforming the elements of the input slice into a new slice of a different type.
The function is generic, allowing it to work with slices of any type `T` as input, and the result can be a slice of any type `U`.
Parameters:
- `slice`: The input slice containing elements of type `T` to be mapped.
- `mapper`: A function that takes an element of type `T` and returns a transformed element of type `U`.
Returns:
- A new slice of type `[]U` containing the mapped elements, with the same length as the input slice, but with elements transformed according to the `mapper` function.
Example:
// Mapping a slice of integers to their string representations
numbers := []int{1, 2, 3}
mappedStrings := ToSlice(numbers, func(n int) string {
return fmt.Sprintf("Number %d", n)
})
// mappedStrings will be []string{"Number 1", "Number 2", "Number 3"}
// Mapping a slice of strings to their lengths
words := []string{"apple", "banana", "cherry"}
mappedLengths := ToSlice(words, func(word string) int {
return len(word)
})
// mappedLengths will be []int{5, 6, 6}
// Mapping an empty slice returns an empty slice
empty := []int{}
mappedEmpty := ToSlice(empty, func(n int) string {
return fmt.Sprintf("Number %d", n)
})
// mappedEmpty will be []string{}
func UnflattenMap ¶
UnflattenMap converts a flat map with dot-separated keys into a nested map structure.
This function takes a flat map `m` where the keys are strings that may contain dot (".") separators, indicating a nested structure. It reconstructs the nested map by splitting the keys at each dot and creating nested maps accordingly.
The function returns a new map where the keys are organized into nested maps based of the original flat map.
Parameters:
- `m`: The flat map to be unflattened. It has string keys and values of type `any`.
- `prefix`: A string prefix to be removed from the keys before processing. This is typically an empty string when the function is called initially.
Returns:
- A new map of type `map[string]any`, where the keys from the input map `m` are organized into a nested structure based on the dot-separated keys.
Example:
flatMap := map[string]any{
"user.name": "Alice",
"user.address.city": "Wonderland",
"user.address.zip": "12345",
"age": 30,
}
unflattened := UnflattenMap(flatMap, "")
// unflattened will be:
// map[string]any{
// "user": map[string]any{
// "name": "Alice",
// "address": map[string]any{
// "city": "Wonderland",
// "zip": "12345",
// },
// },
// "age": 30,
// }
func Unique ¶
func Unique[T comparable](slice []T) []T
Unique returns a new slice containing only the unique elements from the input slice, preserving their original order.
This function iterates over each element in the input slice `slice` and uses a map `uniqueMap` to track elements that have already been encountered. If an element has not been seen before, it is added to both the `uniqueValues` result slice and the map. This ensures that only the first occurrence of each unique element is kept in the final slice, while duplicates are ignored.
The function is generic, allowing it to operate on slices of any comparable type `T`. The elements must be of a comparable type to allow them to be used as keys in the map.
Parameters:
- `slice`: The input slice from which unique elements are extracted. It can contain elements of any comparable type `T`.
Returns:
- A new slice of type `[]T` containing only the unique elements from `slice` in the order of their first appearance.
Example:
// Extracting unique integers from a slice
numbers := []int{1, 2, 2, 3, 4, 4, 5}
uniqueNumbers := Unique(numbers)
// uniqueNumbers will be []int{1, 2, 3, 4, 5}
// Extracting unique strings from a slice
words := []string{"apple", "banana", "apple", "cherry"}
uniqueWords := Unique(words)
// uniqueWords will be []string{"apple", "banana", "cherry"}
// An empty slice will return an empty result
empty := []int{}
uniqueEmpty := Unique(empty)
// uniqueEmpty will be []int{}
func Unshift ¶
func Unshift[T any](slice []T, element T) []T
Unshift inserts an element at the beginning of a slice and returns the resulting slice.
This function takes an input slice `slice` and an element `element`, then creates a new slice by appending the `element` at the start, followed by the elements of the original slice. The function uses the built-in `append` function to combine a new slice containing just the `element` with the original slice, effectively adding the element to the beginning.
The function is generic, allowing it to work with slices of any type `T`.
Parameters:
- `slice`: The input slice to which the element will be prepended. It can contain elements of any type `T`.
- `element`: The element to be inserted at the beginning of the slice. It is of type `T`.
Returns:
- A new slice of type `[]T`, containing `element` followed by all the elements of the original `slice`.
Example:
// Adding an integer to the beginning of a slice of integers
numbers := []int{2, 3, 4}
updatedNumbers := Unshift(numbers, 1)
// updatedNumbers will be []int{1, 2, 3, 4}
// Adding a string to the beginning of a slice of strings
words := []string{"banana", "cherry"}
updatedWords := Unshift(words, "apple")
// updatedWords will be []string{"apple", "banana", "cherry"}
// Adding to an empty slice
var emptySlice []int
newSlice := Unshift(emptySlice, 1)
// newSlice will be []int{1}
func Values ¶
Values extracts and returns the values from a map as a slice.
This function takes a map `m` with keys of type `any` and values of type `V`, and creates a new slice containing all the values from the map. The function iterates over the map and appends each value to the `values` slice. The resulting slice will have the same number of elements as the map has key-value pairs, and the order of values will correspond to the order in which they were iterated over (which is not guaranteed to be in any particular order).
The function is generic, allowing it to work with maps of any key type `K` and value type `V`.
Parameters:
- `m`: The input map from which to extract the values. The keys are of type `any` and the values are of type `V`.
Returns:
- A slice of type `[]V` containing all the values from the map `m`.
Example:
// Extracting values from a map of strings to integers
map1 := map[any]int{"a": 1, "b": 2, "c": 3}
values := Values(map1)
// values will be []int{1, 2, 3}
// Extracting values from a map of strings to strings
map2 := map[any]string{"x": "apple", "y": "banana", "z": "cherry"}
valuesStrings := Values(map2)
// valuesStrings will be []string{"apple", "banana", "cherry"}
// Extracting values from an empty map returns an empty slice
emptyMap := map[any]int{}
emptyValues := Values(emptyMap)
// emptyValues will be []int{}
func ValuesComp ¶
func ValuesComp[K comparable, V, U any](m map[K]V, fn func(V) U) map[K]U
ValuesComp applies a transformation function to each value in a map and returns a new map with the same keys and transformed values.
This function iterates over each key-value pair in the input map `m`, applies the provided transformation function `fn` to each value, and stores the result in a new map `result`. The keys in the resulting map remain the same as in the input map, while the values are transformed according to the function `fn`.
The function is generic, allowing it to work with maps where the keys are of any comparable type `K`, the original values are of type `V`, and the transformed values are of type `U`.
Parameters:
- `m`: The input map with keys of type `K` and values of type `V`.
- `fn`: A function that takes a value of type `V` and returns a transformed value of type `U`.
Returns:
- A new map of type `map[K]U`, where each value is the result of applying `fn` to the corresponding value in the input map `m`.
Example:
// Transforming a map of integers to their string representations
m := map[string]int{"one": 1, "two": 2, "three": 3}
transformed := ValuesComp(m, func(v int) string {
return fmt.Sprintf("Number %d", v)
})
// transformed will be map[string]string{"one": "Number 1", "two": "Number 2", "three": "Number 3"}
Types ¶
type HashMap ¶
type HashMap[K, V comparable] struct { // contains filtered or unexported fields }
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.
func NewHashMap ¶
func NewHashMap[K, V comparable]() *HashMap[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 (*HashMap[K, V]) Clear ¶
func (hash *HashMap[K, V]) Clear()
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 (*HashMap[K, V]) ContainsKey ¶
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 (*HashMap[K, V]) Get ¶
func (hash *HashMap[K, V]) Get(key K) (value V)
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 (*HashMap[K, V]) IsEmpty ¶
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 (*HashMap[K, V]) KeySet ¶
func (hash *HashMap[K, V]) KeySet() []K
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 (*HashMap[K, V]) Put ¶
func (hash *HashMap[K, V]) Put(key K, value V)
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 (*HashMap[K, V]) Remove ¶
func (hash *HashMap[K, V]) Remove(key K)
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.
type HashSet ¶
type HashSet[T comparable] struct { // contains filtered or unexported fields }
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 !=.
func NewHashSet ¶
func NewHashSet[T comparable](elements ...T) *HashSet[T]
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 (*HashSet[T]) Add ¶
func (hash *HashSet[T]) Add(element T)
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 (*HashSet[T]) AddAll ¶
func (hash *HashSet[T]) AddAll(elements ...T)
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 (*HashSet[T]) Clear ¶
func (hash *HashSet[T]) Clear()
Clear removes all elements from the HashSet, resetting it to an empty set.
Example usage:
hashSet.Clear() // Clears all elements from the set.
func (*HashSet[T]) Contains ¶
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 (*HashSet[T]) Difference ¶
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 (*HashSet[T]) Intersection ¶
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 (*HashSet[T]) IsEmpty ¶
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 (*HashSet[T]) Remove ¶
func (hash *HashSet[T]) Remove(element T)
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 (*HashSet[T]) RemoveAll ¶
func (hash *HashSet[T]) RemoveAll(elements ...T)
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 (*HashSet[T]) Size ¶
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 (*HashSet[T]) Slice ¶
func (hash *HashSet[T]) Slice() []T
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 (*HashSet[T]) String ¶
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 (*HashSet[T]) Union ¶
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.
type Stack ¶
type Stack[T comparable] struct { // contains filtered or unexported fields }
Stack is a generic stack data structure that stores elements of type `T`. It provides basic stack operations like push, pop, and peek. The type `T` must be comparable, allowing the stack to handle any type that supports equality comparison.
func NewStack ¶
func NewStack[T comparable]() *Stack[T]
NewStack creates and returns a new, empty stack. Returns:
- A pointer to an empty `Stack`.
Example usage:
stack := NewStack[int]() // Creates a new empty stack of integers.
func (*Stack[T]) Clear ¶
func (stack *Stack[T]) Clear()
Clear removes all elements from the stack, leaving it empty.
Example usage:
stack.Clear() // Clears all elements from the stack.
func (*Stack[T]) IsEmpty ¶
IsEmpty checks whether the stack contains any elements. Returns:
- `true` if the stack is empty, `false` otherwise.
Example usage:
isEmpty := stack.IsEmpty() // Returns true if the stack is empty.
func (*Stack[T]) Peek ¶
func (stack *Stack[T]) Peek() T
Peek returns the top element of the stack without removing it. If the stack is empty, it returns the zero value for type `T`. Returns:
- The top element of the stack, or the zero value of `T` if the stack is empty.
Example usage:
top := stack.Peek() // Gets the top element of the stack without removing it.
func (*Stack[T]) Pop ¶
func (stack *Stack[T]) Pop() T
Pop removes and returns the top element of the stack. If the stack is empty, it returns the zero value for type `T`. Returns:
- The top element of the stack, or the zero value of `T` if the stack is empty.
Example usage:
top := stack.Pop() // Removes and returns the top element of the stack.