Files
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

298 lines
7.0 KiB
Go

package sli
import (
"fmt"
"math/rand"
"reflect"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// 将任意切片类型转换为 []interface{}
func CreateAnyTypeSlice(slice interface{}) []interface{} {
//判断是否是切片类型
v := reflect.ValueOf(slice)
if v.Kind() != reflect.Slice {
return nil
}
sliceLen := v.Len()
out := make([]interface{}, sliceLen)
for i := 0; i < sliceLen; i++ {
out[i] = v.Index(i).Interface()
}
return out
}
// @brief: 删除任意切片类型指定下标的元素
func Delete(slice interface{}, index int) (interface{}, bool) {
//判断是否是切片类型
v := reflect.ValueOf(slice)
if v.Kind() != reflect.Slice {
return nil, false
}
//参数检查
if v.Len() == 0 || index < 0 || index > v.Len()-1 {
return nil, false
}
return reflect.AppendSlice(v.Slice(0, index), v.Slice(index+1, v.Len())).Interface(), true
}
// @brief: 删除任意切片类型指定范围下标的元素
func DeleteIndexRange(slice interface{}, start, end int) (interface{}, bool) {
//判断是否是切片类型
v := reflect.ValueOf(slice)
if v.Kind() != reflect.Slice {
return nil, false
}
//参数检查
if v.Len() == 0 || start < 0 || end > v.Len()-1 {
return nil, false
}
if start == 0 && end == 0 {
return nil, true
}
return reflect.AppendSlice(v.Slice(0, start-1), v.Slice(end+1, v.Len())).Interface(), true
}
// @brief: 删除任意切片类型指定的元素 , 0 表示删除匹配到的第一个元素,1 表示删除匹配到的所有元素
func DeleteSpecifyEle(slice interface{}, spec interface{}, ct ...int) interface{} {
//判断是否是切片类型
isAll := false
v := reflect.ValueOf(slice)
if v.Kind() != reflect.Slice {
return slice
}
//参数检查
if v.Len() == 0 {
return slice
}
if len(ct) == 0 {
isAll = false
} else if ct[0] == 0 {
isAll = false
} else if ct[0] == 1 {
isAll = true
}
var handleSlice interface{}
handleSlice = slice
for i := 0; i < v.Len(); i++ {
fmt.Println(reflect.ValueOf(v.Index(i).Interface()), reflect.ValueOf(spec))
if reflect.ValueOf(v.Index(i).Interface()) == reflect.ValueOf(spec) {
out, suc := Delete(handleSlice, i)
handleSlice = out
if suc {
if !isAll {
return out
}
}
}
}
return handleSlice
}
// 给任意切片类型插入元素
func Insert(slice interface{}, index int, value interface{}) (interface{}, bool) {
//判断是否是切片类型
v := reflect.ValueOf(slice)
if v.Kind() != reflect.Slice {
return nil, false
}
//参数检查
if index < 0 || index > v.Len() || reflect.TypeOf(slice).Elem() != reflect.TypeOf(value) {
return nil, false
}
//尾部追加元素
if index == v.Len() {
return reflect.Append(v, reflect.ValueOf(value)).Interface(), true
}
v = reflect.AppendSlice(v.Slice(0, index+1), v.Slice(index, v.Len()))
v.Index(index).Set(reflect.ValueOf(value))
return v.Interface(), true
}
// 给任意字符串类型数组插入元素
func InsertStringSlice(slice []string, index int, value ...string) []string {
var newStr []string
if index == 0 {
return append(append(newStr, value...), slice...)
}
if index == len(slice)-1 {
return append(append(newStr, slice...), value...)
}
return append(append(append(newStr, slice[0:index]...), value...), slice[index:]...)
}
// 修改任意切片类型指定下标的元素
func Update(slice interface{}, index int, value interface{}) (interface{}, bool) {
//判断是否是切片类型
v := reflect.ValueOf(slice)
if v.Kind() != reflect.Slice {
return nil, false
}
//参数检查
if index > v.Len()-1 || reflect.TypeOf(slice).Elem() != reflect.TypeOf(value) {
return nil, false
}
v.Index(index).Set(reflect.ValueOf(value))
return v.Interface(), true
}
// 查找指定元素在任意切片类型中的所有下标
func Search(slice interface{}, value interface{}) ([]int, bool) {
//判断是否是切片类型
v := reflect.ValueOf(slice)
if v.Kind() != reflect.Slice {
return nil, false
}
index := make([]int, 0, v.Len())
for i := 0; i < v.Len(); i++ {
if v.Index(i).Interface() == reflect.ValueOf(value).Interface() {
index = append(index, i)
}
}
return index, true
}
// 元素去重
func RemoveRep[T comparable](slc []T) []T {
if len(slc) < 1024 {
// 切片长度小于1024的时候,循环来过滤
return RemoveRepByLoop(slc)
}
// 大于的时候,通过map来过滤
return RemoveRepByMap(slc)
}
// 通过map主键唯一的特性过滤重复元素
func RemoveRepByMap[T comparable](slc []T) []T {
result := []T{}
tempMap := map[T]byte{} // 存放不重复主键
for _, e := range slc {
l := len(tempMap)
tempMap[e] = 0
if len(tempMap) != l { // 加入map后,map长度变化,则元素不重复
result = append(result, e)
}
}
return result
}
// 通过map主键唯一的特性过滤重复元素: uint64
func RemoveRepUintByMap(slc []uint64) []uint64 {
result := []uint64{}
tempMap := map[uint64]byte{} // 存放不重复主键
for _, e := range slc {
l := len(tempMap)
tempMap[e] = 0
if len(tempMap) != l { // 加入map后,map长度变化,则元素不重复
result = append(result, e)
}
}
return result
}
// 通过两重循环过滤重复元素
func RemoveRepByLoop[T comparable](slc []T) []T {
result := make([]T, 0, len(slc)) // 存放结果
for i := range slc {
flag := true
for j := range result {
if slc[i] == result[j] {
flag = false // 存在重复元素,标识为false
break
}
}
if flag { // 标识为false,不添加进结果
result = append(result, slc[i])
}
}
return result
}
// RemoveRepObjectID 过滤重复 mongo ID
func RemoveRepObjectID(slc []primitive.ObjectID) []primitive.ObjectID {
res := []primitive.ObjectID{}
m := make(map[primitive.ObjectID]struct{})
for _, v := range slc {
if _, ok := m[v]; !ok {
m[v] = struct{}{}
res = append(res, v)
}
}
return res
}
// objID切片是否存在item
func PrimitiveObjIDIsExist(slc []primitive.ObjectID, item primitive.ObjectID) bool {
flag := false
for i := range slc {
if slc[i] == item {
flag = true
break
}
}
return flag
}
// 是否包含某一个元素
func Contains[T comparable](slc []T, item T) bool {
flag := false
for i := range slc {
if slc[i] == item {
flag = true
break
}
}
return flag
}
func ContainsUint(slc []uint64, item uint64) bool {
flag := false
for i := range slc {
if slc[i] == item {
flag = true
break
}
}
return flag
}
func ContainsInt(slc []int, item int) bool {
flag := false
for i := range slc {
if slc[i] == item {
flag = true
break
}
}
return flag
}
func Shuffle(slice []interface{}) {
for len(slice) > 0 {
n := len(slice)
randIndex := rand.Intn(n)
slice[n-1], slice[randIndex] = slice[randIndex], slice[n-1]
slice = slice[:n-1]
}
}
func ShuffleString(slice []string) {
for len(slice) > 0 {
n := len(slice)
randIndex := rand.Intn(n)
slice[n-1], slice[randIndex] = slice[randIndex], slice[n-1]
slice = slice[:n-1]
}
}
// InSlice 判断元素是否存在于数组中
func InSlice[T any | primitive.ObjectID](i T, s []T) bool {
for _, ii := range s {
if reflect.DeepEqual(i, ii) {
return true
}
}
return false
}