440 lines
11 KiB
Go
440 lines
11 KiB
Go
package dara
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// ArrContains checks if an element is in the array
|
|
func ArrContains(arr interface{}, value interface{}) bool {
|
|
arrValue := reflect.ValueOf(arr)
|
|
valueValue := reflect.ValueOf(value)
|
|
|
|
// Ensure arr is a slice
|
|
if arrValue.Kind() != reflect.Slice {
|
|
return false
|
|
}
|
|
|
|
for i := 0; i < arrValue.Len(); i++ {
|
|
elem := arrValue.Index(i)
|
|
|
|
// Ensure the array element is a pointer
|
|
if elem.Kind() == reflect.Ptr {
|
|
if valueValue.Kind() == reflect.Ptr && elem.Pointer() == valueValue.Pointer() {
|
|
return true
|
|
}
|
|
if elem.Elem().Interface() == valueValue.Interface() {
|
|
return true
|
|
}
|
|
} else if elem.Kind() == reflect.Interface {
|
|
elem = elem.Elem()
|
|
if valueValue.Kind() == reflect.Ptr && elem.Interface() == valueValue.Pointer() {
|
|
return true
|
|
}
|
|
if elem.Interface() == valueValue.Interface() {
|
|
return true // Return the index if found
|
|
}
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// ArrIndex returns the index of the element in the array
|
|
func ArrIndex(arr interface{}, value interface{}) int {
|
|
arrValue := reflect.ValueOf(arr)
|
|
valueValue := reflect.ValueOf(value)
|
|
|
|
// Ensure arr is a slice
|
|
if arrValue.Kind() != reflect.Slice {
|
|
return -1
|
|
}
|
|
|
|
for i := 0; i < arrValue.Len(); i++ {
|
|
elem := arrValue.Index(i)
|
|
|
|
// Ensure the array element is a pointer
|
|
if elem.Kind() == reflect.Ptr {
|
|
// Dereference the pointer to get the underlying value
|
|
if valueValue.Kind() == reflect.Ptr && elem.Pointer() == valueValue.Pointer() {
|
|
return i
|
|
}
|
|
if elem.Elem().Interface() == valueValue.Interface() {
|
|
return i // Return the index if found
|
|
}
|
|
} else if elem.Kind() == reflect.Interface {
|
|
elem = elem.Elem()
|
|
if valueValue.Kind() == reflect.Ptr && elem.Interface() == valueValue.Pointer() {
|
|
return i
|
|
}
|
|
if elem.Interface() == valueValue.Interface() {
|
|
return i // Return the index if found
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1 // Return -1 if not found
|
|
}
|
|
|
|
func handlePointer(elem reflect.Value) string {
|
|
if elem.IsNil() {
|
|
return "" // Skip nil pointers
|
|
}
|
|
|
|
// Dereference the pointer
|
|
elem = elem.Elem()
|
|
return handleValue(elem)
|
|
}
|
|
|
|
func handleValue(elem reflect.Value) string {
|
|
switch elem.Kind() {
|
|
case reflect.String:
|
|
return elem.String()
|
|
case reflect.Int:
|
|
return fmt.Sprintf("%d", elem.Interface())
|
|
case reflect.Float64:
|
|
return fmt.Sprintf("%f", elem.Interface())
|
|
case reflect.Bool:
|
|
return fmt.Sprintf("%t", elem.Interface())
|
|
default:
|
|
return "" // Skip unsupported types
|
|
}
|
|
}
|
|
|
|
func ArrJoin(arr interface{}, sep string) string {
|
|
var strSlice []string
|
|
var str string
|
|
|
|
arrValue := reflect.ValueOf(arr)
|
|
|
|
// Ensure arr is a slice
|
|
if arrValue.Kind() != reflect.Slice {
|
|
return ""
|
|
}
|
|
|
|
for i := 0; i < arrValue.Len(); i++ {
|
|
elem := arrValue.Index(i)
|
|
|
|
if elem.Kind() == reflect.Ptr {
|
|
str = handlePointer(elem)
|
|
} else if elem.Kind() == reflect.Interface {
|
|
str = handleValue(elem.Elem())
|
|
} else {
|
|
str = handleValue(elem)
|
|
}
|
|
|
|
if str != "" {
|
|
strSlice = append(strSlice, str)
|
|
}
|
|
}
|
|
|
|
return strings.Join(strSlice, sep)
|
|
}
|
|
|
|
// ArrShift removes the first element from the array
|
|
func ArrShift(arr interface{}) interface{} {
|
|
arrValue := reflect.ValueOf(arr)
|
|
|
|
// Ensure arr is a pointer to a slice
|
|
if arrValue.Kind() != reflect.Ptr || arrValue.Elem().Kind() != reflect.Slice {
|
|
return nil
|
|
}
|
|
|
|
// Get the slice from the pointer
|
|
sliceValue := arrValue.Elem()
|
|
|
|
// Ensure the slice is not empty
|
|
if sliceValue.Len() == 0 {
|
|
return nil
|
|
}
|
|
|
|
// Get the first element
|
|
firstElem := sliceValue.Index(0)
|
|
|
|
// Create a new slice with one less element
|
|
newArrValue := reflect.MakeSlice(sliceValue.Type(), sliceValue.Len()-1, sliceValue.Cap())
|
|
|
|
// Copy the elements after the first one to the new slice
|
|
reflect.Copy(newArrValue, sliceValue.Slice(1, sliceValue.Len()))
|
|
|
|
// Set the original slice to the new slice
|
|
sliceValue.Set(newArrValue)
|
|
|
|
// Return the removed first element
|
|
return firstElem.Interface()
|
|
}
|
|
|
|
// ArrPop removes the last element from the array
|
|
func ArrPop(arr interface{}) interface{} {
|
|
arrValue := reflect.ValueOf(arr)
|
|
|
|
// Ensure arr is a pointer to a slice
|
|
if arrValue.Kind() != reflect.Ptr || arrValue.Elem().Kind() != reflect.Slice {
|
|
return nil
|
|
}
|
|
|
|
// Get the slice from the pointer
|
|
sliceValue := arrValue.Elem()
|
|
|
|
// Ensure the slice is not empty
|
|
if sliceValue.Len() == 0 {
|
|
return nil
|
|
}
|
|
|
|
// Get the last element
|
|
lastIndex := sliceValue.Len() - 1
|
|
lastElem := sliceValue.Index(lastIndex)
|
|
|
|
// Create a new slice with one less element
|
|
newArrValue := reflect.MakeSlice(sliceValue.Type(), sliceValue.Len()-1, sliceValue.Cap()-1)
|
|
|
|
// Copy the elements before the last one to the new slice
|
|
reflect.Copy(newArrValue, sliceValue.Slice(0, lastIndex))
|
|
|
|
// Set the original slice to the new slice
|
|
sliceValue.Set(newArrValue)
|
|
|
|
// Return the removed last element
|
|
return lastElem.Interface()
|
|
}
|
|
|
|
// ArrUnshift adds an element to the beginning of the array
|
|
func ArrUnshift(arr interface{}, value interface{}) int {
|
|
arrValue := reflect.ValueOf(arr)
|
|
|
|
// Ensure arr is a pointer to a slice
|
|
if arrValue.Kind() != reflect.Ptr || arrValue.Elem().Kind() != reflect.Slice {
|
|
return 0
|
|
}
|
|
|
|
// Get the slice from the pointer
|
|
sliceValue := arrValue.Elem()
|
|
|
|
// Create a new slice with one additional element
|
|
newArrValue := reflect.MakeSlice(sliceValue.Type(), sliceValue.Len()+1, sliceValue.Cap()+1)
|
|
|
|
// Set the new element as the first element
|
|
newArrValue.Index(0).Set(reflect.ValueOf(value))
|
|
|
|
// Copy the old elements to the new slice, starting at index 1
|
|
reflect.Copy(newArrValue.Slice(1, newArrValue.Len()), sliceValue)
|
|
|
|
// Set the original slice to the new slice
|
|
sliceValue.Set(newArrValue)
|
|
|
|
// Return the new length of the slice
|
|
return newArrValue.Len()
|
|
}
|
|
|
|
// ArrPush adds an element to the end of the array
|
|
func ArrPush(arr interface{}, value interface{}) int {
|
|
arrValue := reflect.ValueOf(arr)
|
|
|
|
// Ensure arr is a pointer to a slice
|
|
if arrValue.Kind() != reflect.Ptr || arrValue.Elem().Kind() != reflect.Slice {
|
|
return 0
|
|
}
|
|
|
|
// Get the slice from the pointer
|
|
sliceValue := arrValue.Elem()
|
|
|
|
// Create a new slice with one additional element
|
|
newArrValue := reflect.MakeSlice(sliceValue.Type(), sliceValue.Len()+1, sliceValue.Cap()+1)
|
|
|
|
// Copy the old elements to the new slice
|
|
reflect.Copy(newArrValue, sliceValue)
|
|
|
|
// Set the new element as the last element
|
|
newArrValue.Index(sliceValue.Len()).Set(reflect.ValueOf(value))
|
|
|
|
// Set the original slice to the new slice
|
|
sliceValue.Set(newArrValue)
|
|
|
|
// Return the new length of the slice
|
|
return newArrValue.Len()
|
|
}
|
|
|
|
// ConcatArr concatenates two arrays
|
|
func ConcatArr(arr1 interface{}, arr2 interface{}) interface{} {
|
|
var result []interface{}
|
|
value1 := reflect.ValueOf(arr1)
|
|
value2 := reflect.ValueOf(arr2)
|
|
|
|
// 检查 arr1 和 arr2 是否为切片
|
|
if value1.Kind() != reflect.Slice || value2.Kind() != reflect.Slice {
|
|
panic("ConcatArr: both inputs must be slices")
|
|
}
|
|
|
|
// 如果两个切片的类型相同
|
|
if value1.Type() == value2.Type() {
|
|
// 创建一个新的切片,类型与输入切片相同
|
|
result := reflect.MakeSlice(value1.Type(), 0, value1.Len()+value2.Len())
|
|
|
|
// 复制第一个切片的元素
|
|
for i := 0; i < value1.Len(); i++ {
|
|
result = reflect.Append(result, value1.Index(i))
|
|
}
|
|
// 复制第二个切片的元素
|
|
for i := 0; i < value2.Len(); i++ {
|
|
result = reflect.Append(result, value2.Index(i))
|
|
}
|
|
return result.Interface() // 返回类型相同的切片
|
|
}
|
|
|
|
// 否则返回 []interface{}
|
|
for i := 0; i < value1.Len(); i++ {
|
|
result = append(result, value1.Index(i).Interface())
|
|
}
|
|
for i := 0; i < value2.Len(); i++ {
|
|
result = append(result, value2.Index(i).Interface())
|
|
}
|
|
return result
|
|
}
|
|
|
|
// ArrAppend inserts a new pointer at a specified index in a pointer array.
|
|
func ArrAppend(arr interface{}, value interface{}, index int) {
|
|
arrV := reflect.ValueOf(arr)
|
|
if arrV.Kind() != reflect.Ptr || arrV.Elem().Kind() != reflect.Slice {
|
|
return
|
|
}
|
|
|
|
sliceV := arrV.Elem()
|
|
|
|
if index < 0 || index > sliceV.Len() {
|
|
return
|
|
}
|
|
|
|
valueV := reflect.ValueOf(value)
|
|
|
|
// 创建一个容纳新值的切片
|
|
newSlice := reflect.Append(sliceV, reflect.Zero(sliceV.Type().Elem()))
|
|
reflect.Copy(newSlice.Slice(index+1, newSlice.Len()), newSlice.Slice(index, newSlice.Len()-1))
|
|
newSlice.Index(index).Set(valueV)
|
|
|
|
// 更新原始切片
|
|
sliceV.Set(newSlice)
|
|
return
|
|
}
|
|
|
|
// ArrRemove removes an element from the array
|
|
func ArrRemove(arr interface{}, value interface{}) {
|
|
arrValue := reflect.ValueOf(arr)
|
|
|
|
// Ensure arr is a pointer to a slice
|
|
if arrValue.Kind() != reflect.Ptr || arrValue.Elem().Kind() != reflect.Slice {
|
|
return
|
|
}
|
|
|
|
// Get the slice from the pointer
|
|
slice := arrValue.Elem()
|
|
index := ArrIndex(slice.Interface(), value)
|
|
// If index is found, remove the element at that index
|
|
if index != -1 {
|
|
// Remove the element at the specified index
|
|
newSlice := reflect.MakeSlice(slice.Type(), 0, slice.Len()-1)
|
|
|
|
// Copy elements before the index
|
|
newSlice = reflect.AppendSlice(slice.Slice(0, index), slice.Slice(index+1, slice.Len()))
|
|
// Set the new slice back to the original reference
|
|
slice.Set(newSlice)
|
|
}
|
|
}
|
|
|
|
func SortArr(arr interface{}, order string) interface{} {
|
|
v := reflect.ValueOf(arr)
|
|
if v.Kind() != reflect.Slice {
|
|
panic("SortArr: input must be a slice")
|
|
}
|
|
|
|
// 创建一个新的切片来存储排序结果
|
|
newSlice := reflect.MakeSlice(v.Type(), v.Len(), v.Cap())
|
|
for i := 0; i < v.Len(); i++ {
|
|
newSlice.Index(i).Set(v.Index(i))
|
|
}
|
|
|
|
order = strings.ToLower(order)
|
|
|
|
sort.SliceStable(newSlice.Interface(), func(i, j int) bool {
|
|
return compare(newSlice.Index(i), newSlice.Index(j), order)
|
|
})
|
|
|
|
return newSlice.Interface()
|
|
}
|
|
|
|
func compare(elemI, elemJ reflect.Value, order string) bool {
|
|
valI := reflect.Indirect(elemI)
|
|
valJ := reflect.Indirect(elemJ)
|
|
|
|
// 对interface{}类型处理实际类型
|
|
if elemI.Kind() == reflect.Interface {
|
|
valI = reflect.Indirect(elemI.Elem())
|
|
}
|
|
if elemJ.Kind() == reflect.Interface {
|
|
valJ = reflect.Indirect(elemJ.Elem())
|
|
}
|
|
|
|
if valI.Kind() != valJ.Kind() {
|
|
|
|
if order == "asc" {
|
|
return valI.Kind() < valJ.Kind()
|
|
}
|
|
return valI.Kind() > valJ.Kind()
|
|
|
|
}
|
|
|
|
switch kind := valI.Kind(); kind {
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
return compareNumbers(valI.Int(), valJ.Int(), order)
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
return compareNumbers(int64(valI.Uint()), int64(valJ.Uint()), order)
|
|
case reflect.Float32, reflect.Float64:
|
|
return compareNumbers(valI.Float(), valJ.Float(), order)
|
|
case reflect.String:
|
|
return compareStrings(valI.String(), valJ.String(), order)
|
|
case reflect.Struct:
|
|
return compareStructs(valI, valJ, order)
|
|
default:
|
|
panic("SortArr: unsupported element type")
|
|
}
|
|
}
|
|
|
|
func compareNumbers(a, b interface{}, order string) bool {
|
|
switch order {
|
|
case "asc":
|
|
return a.(int64) < b.(int64)
|
|
case "desc":
|
|
return a.(int64) > b.(int64)
|
|
default:
|
|
return a.(int64) > b.(int64)
|
|
}
|
|
}
|
|
|
|
func compareStrings(a, b string, order string) bool {
|
|
switch order {
|
|
case "asc":
|
|
return a < b
|
|
case "desc":
|
|
return a > b
|
|
default:
|
|
return a > b
|
|
}
|
|
}
|
|
|
|
func compareStructs(valI, valJ reflect.Value, order string) bool {
|
|
if valI.NumField() > 0 && valJ.NumField() > 0 {
|
|
fieldI := reflect.Indirect(valI.Field(0))
|
|
fieldJ := reflect.Indirect(valJ.Field(0))
|
|
if fieldI.Kind() == fieldJ.Kind() {
|
|
switch fieldI.Kind() {
|
|
case reflect.String:
|
|
return compareStrings(fieldI.String(), fieldJ.String(), order)
|
|
case reflect.Int:
|
|
return compareNumbers(fieldI.Int(), fieldJ.Int(), order)
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|