Files
bl/common/utils/tomap.go

87 lines
2.4 KiB
Go
Raw Normal View History

package utils
import "github.com/gogf/gf/v2/util/grand"
// ToMap converts a slice to a map with the keyFunc determining what the key of a value should be.
// Will override any double values.
func ToMap[T any, K comparable](slice []T, keyFunc func(T) K) map[K]T {
m := make(map[K]T, len(slice))
for _, v := range slice {
m[keyFunc(v)] = v
}
return m
}
// ToSliceMap converts a slice to a map with the keyFunc determining what the key of a value should be.
// Will append to the slice if the key already exists.
func ToSliceMap[T any, K comparable](slice []T, keyFunc func(T) K) map[K][]T {
m := make(map[K][]T, len(slice))
for _, v := range slice {
key := keyFunc(v)
m[key] = append(m[key], v)
}
return m
}
// 定义泛型约束:只允许数值类型(整数、浮点数等)
type Number interface {
int | int8 | int16 | int32 | int64 |
uint | uint8 | uint16 | uint32 | uint64 |
float32 | float64
}
// Max 泛型函数:接收两个同类型的 Number 参数,返回最大值
func Max[T Number](a, b T) T {
if a > b {
return a
}
return b
}
// Max 泛型函数:接收两个同类型的 Number 参数,返回最大值
func Min[T Number](a, b T) T {
if a < b {
return a
}
return b
}
// RandomSlice 泛型函数从任意类型的切片中随机选取n个不重复元素
// T: 泛型类型参数any表示兼容任意类型
// slice: 源切片(任意类型)
// n: 要选取的元素数量
// 返回值: 与源切片同类型的新切片包含随机选取的n个元素
func RandomSlice[T any](slice []T, n int) []T {
// 边界条件1n≤0 或 源切片为空 → 返回空切片
if n <= 0 || len(slice) == 0 {
return []T{}
}
// 边界条件2n≥源切片长度 → 返回源切片的拷贝(避免修改原切片)
if n >= len(slice) {
copySlice := make([]T, len(slice))
copy(copySlice, slice)
return copySlice
}
// 步骤1生成源切片的索引切片
indices := make([]int, len(slice))
for i := range indices {
indices[i] = i
}
// 步骤2Fisher-Yates洗牌算法打乱索引保证随机性均匀
for i := len(indices) - 1; i > 0; i-- {
j := grand.Intn(i + 1) // 生成0~i的随机数
indices[i], indices[j] = indices[j], indices[i]
}
// 步骤3取前n个打乱后的索引映射为源切片的元素
result := make([]T, n)
for i := 0; i < n; i++ {
result[i] = slice[indices[i]]
}
return result
}