go4kids/slices.go

193 lines
5.7 KiB
Go

package go4kids
import (
"golang.org/x/exp/constraints"
)
// Number is an interface that represents any number type.
type Number interface {
constraints.Integer | constraints.Float | constraints.Signed | constraints.Unsigned
}
// ReverseSlice reverses a slice of any type.
func ReverseSlice[T any](s []T) []T {
// For each pair of indices i and j, starting at the ends of the slice
// and working toward the middle, swap the elements at those indices.
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
return s
}
// SumSlice is a function that sums the elements of a slice and returns the result.
func SumSlice[T Number](s []T) T {
// Declare a variable of type T to hold the sum.
var sum T
// Iterate over the slice, adding each value to the sum.
for _, v := range s {
sum += v
}
// Return the sum.
return sum
}
// RemoveItems is a function that removes items by value from a slice, up to a "max" times,
// and returns the resulting slice. If max is 0, all items are removed.
func RemoveItems[T comparable](s []T, item T, max int) []T {
var n int
for i := len(s) - 1; i >= 0; i-- { // iterate through slice in reverse
if s[i] == item { // check if item matches
s = append(s[:i], s[i+1:]...) // remove item
n++ // increment counter
}
// check if we've removed the max number of items
if max != 0 && n == max {
break // break out of loop
}
}
return s[:len(s):len(s)] // return slice with capacity equal to its length
}
// RemoveIndex is a function that removes an item by index from a slice and returns the resulting slice.
func RemoveIndex[T any](s []T, i int) []T {
// Remove the item at the given index from the slice.
r := append(s[:i], s[i+1:]...)
// Return the resulting slice, with capacity equal to its length.
return r[:len(r):len(r)]
}
// Contains is a function that checks if a slice contains a given item and returns a boolean.
func Contains[T comparable](s []T, item T) bool {
// Loop over the input slice.
for _, v := range s {
// Return true if the current value in the input slice matches the item.
if v == item {
return true
}
}
// If none of the items in the slice matched the item to check, return false.
return false
}
// ContainsAny is a function that checks if a slice contains any of a given set of items and returns a boolean.
func ContainsAny[T comparable](s []T, items ...T) bool {
// Loop over the input slice.
for _, v := range s {
// Loop over the items to check.
for _, item := range items {
// Return true if the current value in the input slice matches any of the items.
if v == item {
return true
}
}
}
// If none of the items in the slice matched any of the items to check, return false.
return false
}
// Any is a function that checks if any of the items in a slice satisfy a given condition and
// returns true or false accordingly.
func Any[T any](s []T, f func(T) bool) bool {
// Loop over the input slice.
for _, v := range s {
// Apply the filter function to each value in the input slice, and return
// true if any of them satisfy the condition.
if f(v) {
return true
}
}
// If none of the items in the slice satisfied the condition, return false.
return false
}
// All is a function that checks if all items in a slice satisfy a given condition and returns
// true or false accordingly.
func All[T any](s []T, f func(T) bool) bool {
// Loop over the input slice.
for _, v := range s {
// Apply the filter function to each value in the input slice.
if !f(v) {
return false
}
}
// If all items in the slice satisfied the condition, return true.
return true
}
// Filter is a function that filters a slice by a given condition and returns the resulting slice.
func Filter[T any](s []T, f func(T) bool) []T {
// Create an empty slice to hold the results of the filter operation.
var r []T
// Loop over the input slice.
for _, v := range s {
// Apply the filter function to each value in the input slice.
if f(v) {
r = append(r, v)
}
}
// Return the result slice.
return r
}
func Map[T, U any](s []T, f func(T) U) []U {
// Create an empty slice to hold the results of the map operation.
var r []U
// Loop over the input slice.
for _, v := range s {
// Apply the mapping function to each value in the input slice.
// Append the result to the result slice.
r = append(r, f(v))
}
// Return the result slice.
return r
}
// Max returns the maximum value in a slice of numbers.
func Max[T Number](s []T) T {
// Set the maximum value to the first element in the slice.
var max T = s[0]
// Loop through the slice and assign a new maximum value if
// the current value is greater.
for _, v := range s {
if v > max {
max = v
}
}
// Return the maximum value.
return max
}
// Min returns the smallest element in a slice of numbers.
func Min[T Number](s []T) T {
// Set the minimum value to the first element in the slice.
min := s[0]
// Loop over the slice, starting with the second element.
for _, v := range s[1:] {
// If the current element is smaller than the current minimum,
// set the minimum to the current element.
if v < min {
min = v
}
}
return min
}
// Deduplicate removes duplicate elements from a slice and returns the result.
func Deduplicate[T comparable](s []T) []T {
seen := make(map[T]bool) // make a map to record which elements have been seen
var j int // declare a variable to track the index of the new slice
for _, v := range s { // iterate over the original slice
if seen[v] { // if the element has been seen, continue to the next element
continue
}
seen[v] = true // record the element has been seen
s[j] = v // set the element at the new slice
j++ // increment the index of the new slice
}
return s[:j:j] // return the new slice
}