123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- 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
- }
|