Files
bl/common/utils/tomap.go
昔念 bfafd5789d
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
```
feat(utils): 添加切片元素计数功能

新增CountSliceElements函数用于统计切片中各元素的出现次数,
返回map[元素]出现次数的映射关系,支持任意可比较类型的切片元素。

fix(config): 调整地图配置模型默认值设置

修改MapPit结构体中的MinLevel和MaxLevel字段设置,
将数据库约束改为非空并设置默认值为1,确保等级范围配置的有效性。

ref
2026-02-26 22:32:15 +08:00

102 lines
2.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}
// T: 切片元素类型必须是可比较类型满足map键的要求
// 返回值map[T]int - 键为切片元素,值为对应出现次数
func CountSliceElements[T comparable](slice []T) map[T]int {
// 初始化map预设容量为切片长度优化性能
countMap := make(map[T]int, len(slice))
// 遍历切片,统计每个元素的出现次数
for _, v := range slice {
// 若元素已存在,值+1不存在则自动初始化为0后+1
countMap[v]++
}
return countMap
}