Files
tea/dara/array.go
T
2025-03-14 16:27:38 +08:00

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
}