1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
// Package slice provides utility functions for working with slices in Go.
package slice
import (
"slices"
)
// GroupBy groups a slice of items by a key function.
func GroupBy[T any, K comparable](list []T, key func(T) K) map[K][]T {
groups := make(map[K][]T)
for _, item := range list {
k := key(item)
groups[k] = append(groups[k], item)
}
return groups
}
// Take returns the first n elements of the given slice. If there are not
// enough elements in the slice, the whole slice is returned.
func Take[A any](slice []A, n int) []A {
if n > len(slice) {
return slice
}
return slice[:n]
}
// Last returns the last element of a slice and true. If the slice is empty, it
// returns the zero value and false.
func Last[T any](list []T) (T, bool) {
if len(list) == 0 {
var zero T
return zero, false
}
return list[len(list)-1], true
}
// Uniq returns a new slice with all duplicates removed.
func Uniq[T comparable](list []T) []T {
seen := make(map[T]struct{}, len(list))
uniqList := make([]T, 0, len(list))
for _, item := range list {
if _, ok := seen[item]; !ok {
seen[item] = struct{}{}
uniqList = append(uniqList, item)
}
}
return uniqList
}
// Intersperse puts an item between each element of a slice, returning a new
// slice.
func Intersperse[T any](slice []T, insert T) []T {
if len(slice) <= 1 {
return slice
}
// Create a new slice with the required capacity.
result := make([]T, len(slice)*2-1)
for i := range slice {
// Fill the new slice with original elements and the insertion string.
result[i*2] = slice[i]
// Add the insertion string between items (except the last one).
if i < len(slice)-1 {
result[i*2+1] = insert
}
}
return result
}
// ContainsAny checks if any of the given values present in the list.
func ContainsAny[T comparable](list []T, values ...T) bool {
return slices.ContainsFunc(list, func(v T) bool {
return slices.Contains(values, v)
})
}
// Shift removes and returns the first element of a slice.
// It returns the removed element and the modified slice.
// The third return value (ok) indicates whether an element was removed.
func Shift[T any](slice []T) (element T, newSlice []T, ok bool) {
if len(slice) == 0 {
var zero T
return zero, slice, false
}
return slice[0], slice[1:], true
}
// Pop removes and returns the last element of a slice.
// It returns the removed element and the modified slice.
// The third return value (ok) indicates whether an element was removed.
func Pop[T any](slice []T) (element T, newSlice []T, ok bool) {
if len(slice) == 0 {
var zero T
return zero, slice, false
}
lastIdx := len(slice) - 1
return slice[lastIdx], slice[:lastIdx], true
}
// DeleteAt removes and returns the element at the specified index.
// It returns the removed element and the modified slice.
// The third return value (ok) indicates whether an element was removed.
func DeleteAt[T any](slice []T, index int) (element T, newSlice []T, ok bool) {
if index < 0 || index >= len(slice) {
var zero T
return zero, slice, false
}
element = slice[index]
newSlice = slices.Delete(slices.Clone(slice), index, index+1)
return element, newSlice, true
}
// IsSubset checks if all elements of slice a are present in slice b.
func IsSubset[T comparable](a, b []T) bool {
if len(a) > len(b) {
return false
}
set := make(map[T]struct{}, len(b))
for _, item := range b {
set[item] = struct{}{}
}
for _, item := range a {
if _, exists := set[item]; !exists {
return false
}
}
return true
}
|