117 lines
2.4 KiB
Go
117 lines
2.4 KiB
Go
package utils
|
|
|
|
import (
|
|
"golang.org/x/exp/constraints"
|
|
"sort"
|
|
)
|
|
|
|
func SliceConstruct[T any](fn func() T) T {
|
|
return fn()
|
|
}
|
|
|
|
type SliceWalkCallback func(index int) bool // true 继续
|
|
func SliceWalk(length int, cb SliceWalkCallback) {
|
|
for i := 0; i < length; i++ {
|
|
if ok := cb(i); ok {
|
|
continue
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
type SliceIncludeFilter func(index int) bool // 返回 true 继续, false 中断
|
|
func SliceInclude(length int, filter SliceIncludeFilter) (int, bool) {
|
|
for i := 0; i < length; i++ {
|
|
if ok := filter(i); ok {
|
|
return i, true
|
|
}
|
|
}
|
|
return -1, false
|
|
}
|
|
|
|
type SliceConstructNFilter[T any] func(index int) (T, bool) // 返回 是否保留,项值
|
|
func SliceConstructN[T any](length int, filter SliceConstructNFilter[T]) []T {
|
|
ret := make([]T, 0)
|
|
for i := 0; i < length; i++ {
|
|
if item, keep := filter(i); keep {
|
|
ret = append(ret, item)
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
// SliceUnique 使用泛型实现切片去重
|
|
func SliceUnique[T comparable](s []T) []T {
|
|
seen := make(map[T]bool)
|
|
j := 0
|
|
for _, v := range s {
|
|
if _, ok := seen[v]; !ok {
|
|
seen[v] = true
|
|
s[j] = v
|
|
j++
|
|
}
|
|
}
|
|
return s[:j]
|
|
}
|
|
|
|
// SlicesDifference 求两个集合的差集
|
|
func SlicesDifference[T comparable](a, b []T) []T {
|
|
// 使用 map 存储集合 b 的元素,方便快速判断元素是否存在
|
|
seen := make(map[T]struct{}, len(b))
|
|
for _, v := range b {
|
|
seen[v] = struct{}{}
|
|
}
|
|
|
|
// 遍历集合 a,将不在集合 b 中的元素放入新的切片
|
|
diff := make([]T, 0)
|
|
for _, v := range a {
|
|
if _, ok := seen[v]; !ok {
|
|
diff = append(diff, v)
|
|
}
|
|
}
|
|
|
|
return diff
|
|
}
|
|
|
|
func RemoveSlicesElement[T comparable](slice []T, element T) []T {
|
|
// 使用两个指针,一个遍历,一个用来记录有效元素的位置
|
|
j := 0
|
|
for i := range slice {
|
|
if slice[i] != element {
|
|
slice[j] = slice[i]
|
|
j++
|
|
}
|
|
}
|
|
// 返回截取后的切片
|
|
return slice[:j]
|
|
}
|
|
|
|
func SlicesIntersect[T constraints.Ordered | ~string](slice1, slice2 []T) []T {
|
|
dict := make(map[T]int)
|
|
ret := make([]T, 0)
|
|
for _, v1 := range slice1 {
|
|
dict[v1]++
|
|
}
|
|
for _, v2 := range slice2 {
|
|
if _, exists := dict[v2]; exists {
|
|
ret = append(ret, v2)
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func IsSliceEqual[T constraints.Ordered](src []T, dst []T) bool {
|
|
sort.Slice(src, func(i, j int) bool { return src[i] < src[j] })
|
|
sort.Slice(dst, func(i, j int) bool { return dst[i] < dst[j] })
|
|
if len(src) != len(dst) {
|
|
return false
|
|
}
|
|
for i := range src {
|
|
if src[i] != dst[i] {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|