feat: 新增 utils/sher 包,包含了对 slice 及 hash 常用的操作函数。用于未来对 utils/slice 和 utils/hash 包进行替换
This commit is contained in:
parent
a7b0497d4f
commit
515cbc66eb
|
@ -0,0 +1,88 @@
|
||||||
|
package sher
|
||||||
|
|
||||||
|
import (
|
||||||
|
"slices"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CloneMatrix 克隆二维数组
|
||||||
|
func CloneMatrix[S ~[][]V, V any](slice S) S {
|
||||||
|
if slice == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = make(S, len(slice))
|
||||||
|
for i := 0; i < len(slice); i++ {
|
||||||
|
result[i] = CloneSlice(slice[i])
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloneSlice 克隆切片,该函数是 slices.Clone 的快捷方式
|
||||||
|
func CloneSlice[S ~[]V, V any](slice S) S {
|
||||||
|
return slices.Clone(slice)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloneMap 克隆 map
|
||||||
|
func CloneMap[M ~map[K]V, K comparable, V any](m M) M {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = make(M, len(m))
|
||||||
|
for k, v := range m {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloneSliceN 克隆切片为 n 个切片进行返回
|
||||||
|
func CloneSliceN[S ~[]V, V any](slice S, n int) []S {
|
||||||
|
if slice == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = make([]S, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
result[i] = CloneSlice(slice)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloneMapN 克隆 map 为 n 个 map 进行返回
|
||||||
|
func CloneMapN[M ~map[K]V, K comparable, V any](m M, n int) []M {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = make([]M, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
result[i] = CloneMap(m)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloneSlices 克隆多个切片
|
||||||
|
func CloneSlices[S ~[]V, V any](slices ...S) []S {
|
||||||
|
if slices == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = make([]S, len(slices))
|
||||||
|
for i, slice := range slices {
|
||||||
|
result[i] = CloneSlice(slice)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloneMaps 克隆多个 map
|
||||||
|
func CloneMaps[M ~map[K]V, K comparable, V any](maps ...M) []M {
|
||||||
|
if maps == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = make([]M, len(maps))
|
||||||
|
for i, m := range maps {
|
||||||
|
result[i] = CloneMap(m)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
|
@ -0,0 +1,308 @@
|
||||||
|
package sher
|
||||||
|
|
||||||
|
import "sort"
|
||||||
|
|
||||||
|
type ComparisonHandler[V any] func(source, target V) bool
|
||||||
|
|
||||||
|
// InSlice 判断切片中是否包含某个元素
|
||||||
|
func InSlice[S ~[]V, V any](slice S, v V, handler ComparisonHandler[V]) bool {
|
||||||
|
if slice == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, value := range slice {
|
||||||
|
if handler(v, value) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// InSliceByBinarySearch 判断切片中是否包含某个元素,使用二分搜索
|
||||||
|
func InSliceByBinarySearch[S ~[]V, V any](slice S, v V, handler ComparisonHandler[V]) bool {
|
||||||
|
return sort.Search(len(slice), func(i int) bool {
|
||||||
|
return handler(v, slice[i])
|
||||||
|
}) != len(slice)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllInSlice 判断切片中是否包含所有元素
|
||||||
|
func AllInSlice[S ~[]V, V any](slice S, values []V, handler ComparisonHandler[V]) bool {
|
||||||
|
if slice == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, value := range values {
|
||||||
|
if !InSlice(slice, value, handler) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllInSliceByBinarySearch 判断切片中是否包含所有元素,使用二分搜索
|
||||||
|
func AllInSliceByBinarySearch[S ~[]V, V any](slice S, values []V, handler ComparisonHandler[V]) bool {
|
||||||
|
if slice == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, value := range values {
|
||||||
|
if !InSliceByBinarySearch(slice, value, handler) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnyInSlice 判断切片中是否包含任意一个元素
|
||||||
|
func AnyInSlice[S ~[]V, V any](slice S, values []V, handler ComparisonHandler[V]) bool {
|
||||||
|
if slice == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, value := range values {
|
||||||
|
if InSlice(slice, value, handler) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnyInSliceByBinarySearch 判断切片中是否包含任意一个元素,使用二分搜索
|
||||||
|
func AnyInSliceByBinarySearch[S ~[]V, V any](slice S, values []V, handler ComparisonHandler[V]) bool {
|
||||||
|
if slice == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, value := range values {
|
||||||
|
if InSliceByBinarySearch(slice, value, handler) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// InSlices 判断多个切片中是否包含某个元素
|
||||||
|
func InSlices[S ~[]V, V any](slices []S, v V, handler ComparisonHandler[V]) bool {
|
||||||
|
return InSlice(MergeSlices(slices...), v, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InSlicesByBinarySearch 判断多个切片中是否包含某个元素,使用二分搜索
|
||||||
|
func InSlicesByBinarySearch[S ~[]V, V any](slices []S, v V, handler ComparisonHandler[V]) bool {
|
||||||
|
return InSliceByBinarySearch(MergeSlices(slices...), v, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllInSlices 判断多个切片中是否包含所有元素
|
||||||
|
func AllInSlices[S ~[]V, V any](slices []S, values []V, handler ComparisonHandler[V]) bool {
|
||||||
|
return AllInSlice(MergeSlices(slices...), values, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllInSlicesByBinarySearch 判断多个切片中是否包含所有元素,使用二分搜索
|
||||||
|
func AllInSlicesByBinarySearch[S ~[]V, V any](slices []S, values []V, handler ComparisonHandler[V]) bool {
|
||||||
|
return AllInSliceByBinarySearch(MergeSlices(slices...), values, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnyInSlices 判断多个切片中是否包含任意一个元素
|
||||||
|
func AnyInSlices[S ~[]V, V any](slices []S, values []V, handler ComparisonHandler[V]) bool {
|
||||||
|
return AnyInSlice(MergeSlices(slices...), values, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnyInSlicesByBinarySearch 判断多个切片中是否包含任意一个元素,使用二分搜索
|
||||||
|
func AnyInSlicesByBinarySearch[S ~[]V, V any](slices []S, values []V, handler ComparisonHandler[V]) bool {
|
||||||
|
return AnyInSliceByBinarySearch(MergeSlices(slices...), values, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InAllSlices 判断元素是否在所有切片中都存在
|
||||||
|
func InAllSlices[S ~[]V, V any](slices []S, v V, handler ComparisonHandler[V]) bool {
|
||||||
|
if slices == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, slice := range slices {
|
||||||
|
if !InSlice(slice, v, handler) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// InAllSlicesByBinarySearch 判断元素是否在所有切片中都存在,使用二分搜索
|
||||||
|
func InAllSlicesByBinarySearch[S ~[]V, V any](slices []S, v V, handler ComparisonHandler[V]) bool {
|
||||||
|
if slices == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, slice := range slices {
|
||||||
|
if !InSliceByBinarySearch(slice, v, handler) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnyInAllSlices 判断元素是否在所有切片中都存在任意至少一个
|
||||||
|
func AnyInAllSlices[S ~[]V, V any](slices []S, v []V, handler ComparisonHandler[V]) bool {
|
||||||
|
if slices == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, slice := range slices {
|
||||||
|
if AnyInSlice(slice, v, handler) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnyInAllSlicesByBinarySearch 判断元素是否在所有切片中都存在任意至少一个,使用二分搜索
|
||||||
|
func AnyInAllSlicesByBinarySearch[S ~[]V, V any](slices []S, v []V, handler ComparisonHandler[V]) bool {
|
||||||
|
if slices == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, slice := range slices {
|
||||||
|
if AnyInSliceByBinarySearch(slice, v, handler) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyInMap 判断 map 中是否包含某个 key
|
||||||
|
func KeyInMap[M ~map[K]V, K comparable, V any](m M, key K) bool {
|
||||||
|
_, ok := m[key]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValueInMap 判断 map 中是否包含某个 value
|
||||||
|
func ValueInMap[M ~map[K]V, K comparable, V any](m M, value V, handler ComparisonHandler[V]) bool {
|
||||||
|
if m == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, v := range m {
|
||||||
|
if handler(value, v) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllKeyInMap 判断 map 中是否包含所有 key
|
||||||
|
func AllKeyInMap[M ~map[K]V, K comparable, V any](m M, keys ...K) bool {
|
||||||
|
if m == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, key := range keys {
|
||||||
|
if !KeyInMap(m, key) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllValueInMap 判断 map 中是否包含所有 value
|
||||||
|
func AllValueInMap[M ~map[K]V, K comparable, V any](m M, values []V, handler ComparisonHandler[V]) bool {
|
||||||
|
if m == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, value := range values {
|
||||||
|
if !ValueInMap(m, value, handler) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnyKeyInMap 判断 map 中是否包含任意一个 key
|
||||||
|
func AnyKeyInMap[M ~map[K]V, K comparable, V any](m M, keys ...K) bool {
|
||||||
|
if m == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, key := range keys {
|
||||||
|
if KeyInMap(m, key) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnyValueInMap 判断 map 中是否包含任意一个 value
|
||||||
|
func AnyValueInMap[M ~map[K]V, K comparable, V any](m M, values []V, handler ComparisonHandler[V]) bool {
|
||||||
|
if m == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, value := range values {
|
||||||
|
if ValueInMap(m, value, handler) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllKeyInMaps 判断多个 map 中是否包含所有 key
|
||||||
|
func AllKeyInMaps[M ~map[K]V, K comparable, V any](maps []M, keys ...K) bool {
|
||||||
|
if maps == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, m := range maps {
|
||||||
|
if !AllKeyInMap(m, keys...) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllValueInMaps 判断多个 map 中是否包含所有 value
|
||||||
|
func AllValueInMaps[M ~map[K]V, K comparable, V any](maps []M, values []V, handler ComparisonHandler[V]) bool {
|
||||||
|
if maps == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, m := range maps {
|
||||||
|
if !AllValueInMap(m, values, handler) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnyKeyInMaps 判断多个 map 中是否包含任意一个 key
|
||||||
|
func AnyKeyInMaps[M ~map[K]V, K comparable, V any](maps []M, keys ...K) bool {
|
||||||
|
if maps == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, m := range maps {
|
||||||
|
if AnyKeyInMap(m, keys...) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnyValueInMaps 判断多个 map 中是否包含任意一个 value
|
||||||
|
func AnyValueInMaps[M ~map[K]V, K comparable, V any](maps []M, values []V, handler ComparisonHandler[V]) bool {
|
||||||
|
if maps == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, m := range maps {
|
||||||
|
if AnyValueInMap(m, values, handler) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// InAllMaps 判断元素是否在所有 map 中都存在
|
||||||
|
func InAllMaps[M ~map[K]V, K comparable, V any](maps []M, key K) bool {
|
||||||
|
if maps == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, m := range maps {
|
||||||
|
if !KeyInMap(m, key) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnyInAllMaps 判断元素是否在所有 map 中都存在任意至少一个
|
||||||
|
func AnyInAllMaps[M ~map[K]V, K comparable, V any](maps []M, keys []K) bool {
|
||||||
|
if maps == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, m := range maps {
|
||||||
|
if AnyKeyInMap(m, keys...) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
// Package sher 用于对 slice 和 map 操作的工具函数,将逐步替代 utils/slice 和 utils/map
|
||||||
|
package sher
|
|
@ -0,0 +1,137 @@
|
||||||
|
package sher
|
||||||
|
|
||||||
|
// FilterOutByIndices 过滤切片中特定索引的元素,返回过滤后的切片
|
||||||
|
func FilterOutByIndices[S ~[]V, V any](slice S, indices ...int) S {
|
||||||
|
if slice == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(indices) == 0 {
|
||||||
|
return slice
|
||||||
|
}
|
||||||
|
|
||||||
|
excludeMap := make(map[int]bool)
|
||||||
|
for _, ex := range indices {
|
||||||
|
excludeMap[ex] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
validElements := make([]V, 0, len(slice)-len(excludeMap))
|
||||||
|
for i, v := range slice {
|
||||||
|
if !excludeMap[i] {
|
||||||
|
validElements = append(validElements, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return validElements
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterOutByCondition 过滤切片中符合条件的元素,返回过滤后的切片
|
||||||
|
// - condition 的返回值为 true 时,将会过滤掉该元素
|
||||||
|
func FilterOutByCondition[S ~[]V, V any](slice S, condition func(v V) bool) S {
|
||||||
|
if slice == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if condition == nil {
|
||||||
|
return slice
|
||||||
|
}
|
||||||
|
|
||||||
|
validElements := make([]V, 0, len(slice))
|
||||||
|
for _, v := range slice {
|
||||||
|
if !condition(v) {
|
||||||
|
validElements = append(validElements, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return validElements
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterOutByKey 过滤 map 中特定的 key,返回过滤后的 map
|
||||||
|
func FilterOutByKey[M ~map[K]V, K comparable, V any](m M, key K) M {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
validMap := make(M, len(m)-1)
|
||||||
|
for k, v := range m {
|
||||||
|
if k != key {
|
||||||
|
validMap[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return validMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterOutByValue 过滤 map 中特定的 value,返回过滤后的 map
|
||||||
|
func FilterOutByValue[M ~map[K]V, K comparable, V any](m M, value V, handler ComparisonHandler[V]) M {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
validMap := make(M, len(m))
|
||||||
|
for k, v := range m {
|
||||||
|
if !handler(value, v) {
|
||||||
|
validMap[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return validMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterOutByKeys 过滤 map 中多个 key,返回过滤后的 map
|
||||||
|
func FilterOutByKeys[M ~map[K]V, K comparable, V any](m M, keys ...K) M {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(keys) == 0 {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
validMap := make(M, len(m)-len(keys))
|
||||||
|
for k, v := range m {
|
||||||
|
if !InSlice(keys, k, func(source, target K) bool {
|
||||||
|
return source == target
|
||||||
|
}) {
|
||||||
|
validMap[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return validMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterOutByValues 过滤 map 中多个 value,返回过滤后的 map
|
||||||
|
func FilterOutByValues[M ~map[K]V, K comparable, V any](m M, values []V, handler ComparisonHandler[V]) M {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(values) == 0 {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
validMap := make(M, len(m))
|
||||||
|
for k, v := range m {
|
||||||
|
if !InSlice(values, v, handler) {
|
||||||
|
validMap[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return validMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterOutByMap 过滤 map 中符合条件的元素,返回过滤后的 map
|
||||||
|
// - condition 的返回值为 true 时,将会过滤掉该元素
|
||||||
|
func FilterOutByMap[M ~map[K]V, K comparable, V any](m M, condition func(k K, v V) bool) M {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if condition == nil {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
validMap := make(M, len(m))
|
||||||
|
for k, v := range m {
|
||||||
|
if condition(k, v) {
|
||||||
|
validMap[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return validMap
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package sher
|
||||||
|
|
||||||
|
import "github.com/kercylan98/minotaur/utils/generic"
|
||||||
|
|
||||||
|
// FindMinimumInSlice 获取切片中的最小值
|
||||||
|
func FindMinimumInSlice[S ~[]V, V generic.Number](slice S, handler ComparisonHandler[V]) (result V) {
|
||||||
|
if slice == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
result = slice[0]
|
||||||
|
for i := 1; i < len(slice); i++ {
|
||||||
|
if handler(slice[i], result) {
|
||||||
|
result = slice[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindMaximumInSlice 获取切片中的最大值
|
||||||
|
func FindMaximumInSlice[S ~[]V, V generic.Number](slice S, handler ComparisonHandler[V]) (result V) {
|
||||||
|
if slice == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
result = slice[0]
|
||||||
|
for i := 1; i < len(slice); i++ {
|
||||||
|
if handler(result, slice[i]) {
|
||||||
|
result = slice[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindMin2MaxInSlice 获取切片中的最小值和最大值
|
||||||
|
func FindMin2MaxInSlice[S ~[]V, V generic.Number](slice S, handler ComparisonHandler[V]) (min, max V) {
|
||||||
|
if slice == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
min = slice[0]
|
||||||
|
max = slice[0]
|
||||||
|
for i := 1; i < len(slice); i++ {
|
||||||
|
if handler(slice[i], min) {
|
||||||
|
min = slice[i]
|
||||||
|
}
|
||||||
|
if handler(max, slice[i]) {
|
||||||
|
max = slice[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindMinFromMap 获取 map 中的最小值
|
||||||
|
func FindMinFromMap[M ~map[K]V, K comparable, V generic.Number](m M, handler ComparisonHandler[V]) (result V) {
|
||||||
|
if m == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, v := range m {
|
||||||
|
if handler(v, result) {
|
||||||
|
result = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindMaxFromMap 获取 map 中的最大值
|
||||||
|
func FindMaxFromMap[M ~map[K]V, K comparable, V generic.Number](m M, handler ComparisonHandler[V]) (result V) {
|
||||||
|
if m == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, v := range m {
|
||||||
|
if handler(result, v) {
|
||||||
|
result = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindMin2MaxFromMap 获取 map 中的最小值和最大值
|
||||||
|
func FindMin2MaxFromMap[M ~map[K]V, K comparable, V generic.Number](m M, handler ComparisonHandler[V]) (min, max V) {
|
||||||
|
if m == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, v := range m {
|
||||||
|
if handler(v, min) {
|
||||||
|
min = v
|
||||||
|
}
|
||||||
|
if handler(max, v) {
|
||||||
|
max = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package sher
|
||||||
|
|
||||||
|
// MergeSlices 合并切片
|
||||||
|
func MergeSlices[S ~[]V, V any](slices ...S) (result S) {
|
||||||
|
if len(slices) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var length int
|
||||||
|
for _, slice := range slices {
|
||||||
|
length += len(slice)
|
||||||
|
}
|
||||||
|
|
||||||
|
result = make(S, 0, length)
|
||||||
|
for _, slice := range slices {
|
||||||
|
result = append(result, slice...)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeMaps 合并 map,当多个 map 中存在相同的 key 时,后面的 map 中的 key 将会覆盖前面的 map 中的 key
|
||||||
|
func MergeMaps[M ~map[K]V, K comparable, V any](maps ...M) (result M) {
|
||||||
|
if len(maps) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var length int
|
||||||
|
for _, m := range maps {
|
||||||
|
length += len(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
result = make(M, length)
|
||||||
|
for _, m := range maps {
|
||||||
|
for k, v := range m {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeMapsWithSkip 合并 map,当多个 map 中存在相同的 key 时,后面的 map 中的 key 将会被跳过
|
||||||
|
func MergeMapsWithSkip[M ~map[K]V, K comparable, V any](maps ...M) (result M) {
|
||||||
|
if len(maps) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result = make(M)
|
||||||
|
for _, m := range maps {
|
||||||
|
for k, v := range m {
|
||||||
|
if _, ok := result[k]; !ok {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,239 @@
|
||||||
|
package sher
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/kercylan98/minotaur/utils/random"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ChooseRandomSliceElementRepeatN 获取切片中的 n 个随机元素,允许重复
|
||||||
|
// - 如果 n 大于切片长度或小于 0 时将会发生 panic
|
||||||
|
func ChooseRandomSliceElementRepeatN[S ~[]V, V any](slice S, n int) (result []V) {
|
||||||
|
if slice == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n > len(slice) || n < 0 {
|
||||||
|
panic(fmt.Errorf("n is greater than the length of the slice or less than 0, n: %d, length: %d", n, len(slice)))
|
||||||
|
}
|
||||||
|
result = make([]V, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
result[i] = slice[random.Int(0, len(slice)-1)]
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChooseRandomIndexRepeatN 获取切片中的 n 个随机元素的索引,允许重复
|
||||||
|
// - 如果 n 大于切片长度或小于 0 时将会发生 panic
|
||||||
|
func ChooseRandomIndexRepeatN[S ~[]V, V any](slice S, n int) (result []int) {
|
||||||
|
if slice == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n > len(slice) || n < 0 {
|
||||||
|
panic(fmt.Errorf("n is greater than the length of the slice or less than 0, n: %d, length: %d", n, len(slice)))
|
||||||
|
}
|
||||||
|
result = make([]int, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
result[i] = random.Int(0, len(slice)-1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChooseRandomSliceElement 获取切片中的随机元素
|
||||||
|
func ChooseRandomSliceElement[S ~[]V, V any](slice S) (v V) {
|
||||||
|
if slice == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return slice[random.Int(0, len(slice)-1)]
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChooseRandomIndex 获取切片中的随机元素的索引
|
||||||
|
func ChooseRandomIndex[S ~[]V, V any](slice S) (index int) {
|
||||||
|
if slice == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return random.Int(0, len(slice)-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChooseRandomSliceElementN 获取切片中的 n 个随机元素
|
||||||
|
// - 如果 n 大于切片长度或小于 0 时将会发生 panic
|
||||||
|
func ChooseRandomSliceElementN[S ~[]V, V any](slice S, n int) (result []V) {
|
||||||
|
if slice == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n > len(slice) || n < 0 {
|
||||||
|
panic(fmt.Errorf("n is greater than the length of the slice or less than 0, n: %d, length: %d", n, len(slice)))
|
||||||
|
}
|
||||||
|
result = make([]V, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
result[i] = slice[random.Int(0, len(slice)-1)]
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChooseRandomIndexN 获取切片中的 n 个随机元素的索引
|
||||||
|
// - 如果 n 大于切片长度或小于 0 时将会发生 panic
|
||||||
|
func ChooseRandomIndexN[S ~[]V, V any](slice S, n int) (result []int) {
|
||||||
|
if slice == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n > len(slice) || n < 0 {
|
||||||
|
panic(fmt.Errorf("n is greater than the length of the slice or less than 0, n: %d, length: %d", n, len(slice)))
|
||||||
|
}
|
||||||
|
result = make([]int, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
result[i] = random.Int(0, len(slice)-1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChooseRandomMapKeyRepeatN 获取 map 中的 n 个随机 key,允许重复
|
||||||
|
// - 如果 n 大于 map 长度或小于 0 时将会发生 panic
|
||||||
|
func ChooseRandomMapKeyRepeatN[M ~map[K]V, K comparable, V any](m M, n int) (result []K) {
|
||||||
|
if m == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n > len(m) || n < 0 {
|
||||||
|
panic(fmt.Errorf("n is greater than the length of the map or less than 0, n: %d, length: %d", n, len(m)))
|
||||||
|
}
|
||||||
|
result = make([]K, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
for k := range m {
|
||||||
|
result[i] = k
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChooseRandomMapValueRepeatN 获取 map 中的 n 个随机 value,允许重复
|
||||||
|
// - 如果 n 大于 map 长度或小于 0 时将会发生 panic
|
||||||
|
func ChooseRandomMapValueRepeatN[M ~map[K]V, K comparable, V any](m M, n int) (result []V) {
|
||||||
|
if m == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n > len(m) || n < 0 {
|
||||||
|
panic(fmt.Errorf("n is greater than the length of the map or less than 0, n: %d, length: %d", n, len(m)))
|
||||||
|
}
|
||||||
|
result = make([]V, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
for _, v := range m {
|
||||||
|
result[i] = v
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChooseRandomMapKeyAndValueRepeatN 获取 map 中的 n 个随机 key 和 value,允许重复
|
||||||
|
// - 如果 n 大于 map 长度或小于 0 时将会发生 panic
|
||||||
|
func ChooseRandomMapKeyAndValueRepeatN[M ~map[K]V, K comparable, V any](m M, n int) M {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if n > len(m) || n < 0 {
|
||||||
|
panic(fmt.Errorf("n is greater than the length of the map or less than 0, n: %d, length: %d", n, len(m)))
|
||||||
|
}
|
||||||
|
result := make(M, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
for k, v := range m {
|
||||||
|
result[k] = v
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChooseRandomMapKey 获取 map 中的随机 key
|
||||||
|
func ChooseRandomMapKey[M ~map[K]V, K comparable, V any](m M) (k K) {
|
||||||
|
if m == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for k = range m {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChooseRandomMapValue 获取 map 中的随机 value
|
||||||
|
func ChooseRandomMapValue[M ~map[K]V, K comparable, V any](m M) (v V) {
|
||||||
|
if m == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, v = range m {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChooseRandomMapKeyN 获取 map 中的 n 个随机 key
|
||||||
|
// - 如果 n 大于 map 长度或小于 0 时将会发生 panic
|
||||||
|
func ChooseRandomMapKeyN[M ~map[K]V, K comparable, V any](m M, n int) (result []K) {
|
||||||
|
if m == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n > len(m) || n < 0 {
|
||||||
|
panic(fmt.Errorf("n is greater than the length of the map or less than 0, n: %d, length: %d", n, len(m)))
|
||||||
|
}
|
||||||
|
result = make([]K, n)
|
||||||
|
i := 0
|
||||||
|
for k := range m {
|
||||||
|
result[i] = k
|
||||||
|
i++
|
||||||
|
if i == n {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChooseRandomMapValueN 获取 map 中的 n 个随机 value
|
||||||
|
// - 如果 n 大于 map 长度或小于 0 时将会发生 panic
|
||||||
|
func ChooseRandomMapValueN[M ~map[K]V, K comparable, V any](m M, n int) (result []V) {
|
||||||
|
if m == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n > len(m) || n < 0 {
|
||||||
|
panic(fmt.Errorf("n is greater than the length of the map or less than 0, n: %d, length: %d", n, len(m)))
|
||||||
|
}
|
||||||
|
result = make([]V, n)
|
||||||
|
i := 0
|
||||||
|
for _, v := range m {
|
||||||
|
result[i] = v
|
||||||
|
i++
|
||||||
|
if i == n {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChooseRandomMapKeyAndValue 获取 map 中的随机 key 和 value
|
||||||
|
func ChooseRandomMapKeyAndValue[M ~map[K]V, K comparable, V any](m M) (k K, v V) {
|
||||||
|
if m == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for k, v = range m {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChooseRandomMapKeyAndValueN 获取 map 中的 n 个随机 key 和 value
|
||||||
|
// - 如果 n 大于 map 长度或小于 0 时将会发生 panic
|
||||||
|
func ChooseRandomMapKeyAndValueN[M ~map[K]V, K comparable, V any](m M, n int) M {
|
||||||
|
if m == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if n > len(m) || n < 0 {
|
||||||
|
panic(fmt.Errorf("n is greater than the length of the map or less than 0, n: %d, length: %d", n, len(m)))
|
||||||
|
}
|
||||||
|
result := make(M, n)
|
||||||
|
i := 0
|
||||||
|
for k, v := range m {
|
||||||
|
result[k] = v
|
||||||
|
i++
|
||||||
|
if i == n {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package sher
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kercylan98/minotaur/utils/generic"
|
||||||
|
"github.com/kercylan98/minotaur/utils/random"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Desc 对切片进行降序排序
|
||||||
|
func Desc[S ~[]V, V any, Sort generic.Ordered](slice *S, getter func(index int) Sort) {
|
||||||
|
sort.Slice(*slice, func(i, j int) bool {
|
||||||
|
return getter(i) > getter(j)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// DescByClone 对切片进行降序排序,返回排序后的切片
|
||||||
|
func DescByClone[S ~[]V, V any, Sort generic.Ordered](slice S, getter func(index int) Sort) S {
|
||||||
|
result := CloneSlice(slice)
|
||||||
|
Desc(&result, getter)
|
||||||
|
return result
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Asc 对切片进行升序排序
|
||||||
|
func Asc[S ~[]V, V any, Sort generic.Ordered](slice *S, getter func(index int) Sort) {
|
||||||
|
sort.Slice(*slice, func(i, j int) bool {
|
||||||
|
return getter(i) < getter(j)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AscByClone 对切片进行升序排序,返回排序后的切片
|
||||||
|
func AscByClone[S ~[]V, V any, Sort generic.Ordered](slice S, getter func(index int) Sort) S {
|
||||||
|
result := CloneSlice(slice)
|
||||||
|
Asc(&result, getter)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shuffle 对切片进行随机排序
|
||||||
|
func Shuffle[S ~[]V, V any](slice *S) {
|
||||||
|
sort.Slice(*slice, func(i, j int) bool {
|
||||||
|
return random.Int(0, 1) == 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShuffleByClone 对切片进行随机排序,返回排序后的切片
|
||||||
|
func ShuffleByClone[S ~[]V, V any](slice S) S {
|
||||||
|
result := CloneSlice(slice)
|
||||||
|
Shuffle(&result)
|
||||||
|
return result
|
||||||
|
}
|
Loading…
Reference in New Issue