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