298 lines
7.0 KiB
Go
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
|
|
}
|