// Package sliceutils contains various generic functions for applying an operation across an entire slice package sliceutils // Map applies a given function to every element of a slice. // The return type may be different from the initial type of the slice. func Map[T any, M any](arr []T, apply func(T) M) []M { n := make([]M, len(arr)) for i, e := range arr { n[i] = apply(e) } return n } // Filter filters a slice using a given function. // If the filter function returns true, the element stays, otherwise it gets removed. func Filter[T any](arr []T, filter func(T) bool) []T { n := make([]T, 0) for _, e := range arr { if filter(e) { n = append(n, e) } } return n } // RemoveDuplicate removes all duplicates inside a slice. func RemoveDuplicate[T comparable](sliceList []T) []T { allKeys := make(map[T]bool) list := []T{} for _, item := range sliceList { if _, value := allKeys[item]; !value { allKeys[item] = true list = append(list, item) } } return list } // Reverse reverses a given slice. func Reverse[E any](s []E) { for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { s[i], s[j] = s[j], s[i] } } // CompareOrdered compares two slices for both element equality and element order. func CompareOrdered[T comparable](a, b []T) bool { if len(a) != len(b) { return false } for i, v := range a { if b[i] != v { return false } } return true } // CompareUnorderedS compares two slices for element equality. // The order of those elements does not matter. func CompareUnordered[T comparable](a, b []T) bool { if len(a) != len(b) { return false } hits := 0 for _, v := range a { for _, o := range b { if o == v { hits += 1 } } } return hits == len(a) } // Returns whether b exists inside a using a simple == comparison func Contains[T comparable](a []T, b T) bool { for _, v := range a { if v == b { return true } } return false } // Returns whether the given function f returns true for any element in a func ContainsFunc[T any](a []T, f func(t T) bool) bool { for _, v := range a { if f(v) { return true } } return false } // Compact the slice a using the compactor function. // For the first call, the accumulator argument will be the default value func Compact[T any](a []T, compactor func(acc T, next T) T) T { var acc T for _, v := range a { acc = compactor(acc, v) } return acc } // Returns a channel that all elements in a will be written to in order. // Once all values of a have been sent, the channel will be closed. // The channel must be fully consumed until closed. Otherwise a goroutine will be leaked func ToChannel[T any](a []T) chan T { c := make(chan T) go func() { for _, v := range a { c <- v } close(c) }() return c } // FromChannel reads from a channel until closed, appending every element to a slice. // If you do not know how many elements to expect, use an expectedSize of 0 func FromChannel[T any](c chan T, expectedSize uint) []T { a := make([]T, expectedSize) for v := range c { a = append(a, v) } return a }