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 { // 边界条件1:n≤0 或 源切片为空 → 返回空切片 if n <= 0 || len(slice) == 0 { return []T{} } // 边界条件2:n≥源切片长度 → 返回源切片的拷贝(避免修改原切片) 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 } // 步骤2:Fisher-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 }