193 lines
5.7 KiB
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
|
|
}
|