github.com/alibabacloud-go/tea@v1.3.10/dara/array.go (about)

     1  package dara
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"sort"
     7  	"strings"
     8  )
     9  
    10  // ArrContains checks if an element is in the array
    11  func ArrContains(arr interface{}, value interface{}) bool {
    12  	arrValue := reflect.ValueOf(arr)
    13  	valueValue := reflect.ValueOf(value)
    14  
    15  	// Ensure arr is a slice
    16  	if arrValue.Kind() != reflect.Slice {
    17  		return false
    18  	}
    19  
    20  	for i := 0; i < arrValue.Len(); i++ {
    21  		elem := arrValue.Index(i)
    22  
    23  		// Ensure the array element is a pointer
    24  		if elem.Kind() == reflect.Ptr {
    25  			if valueValue.Kind() == reflect.Ptr && elem.Pointer() == valueValue.Pointer() {
    26  				return true
    27  			}
    28  			if elem.Elem().Interface() == valueValue.Interface() {
    29  				return true
    30  			}
    31  		} else if elem.Kind() == reflect.Interface {
    32  			elem = elem.Elem()
    33  			if valueValue.Kind() == reflect.Ptr && elem.Interface() == valueValue.Pointer() {
    34  				return true
    35  			}
    36  			if elem.Interface() == valueValue.Interface() {
    37  				return true // Return the index if found
    38  			}
    39  		}
    40  	}
    41  
    42  	return false
    43  }
    44  
    45  // ArrIndex returns the index of the element in the array
    46  func ArrIndex(arr interface{}, value interface{}) int {
    47  	arrValue := reflect.ValueOf(arr)
    48  	valueValue := reflect.ValueOf(value)
    49  
    50  	// Ensure arr is a slice
    51  	if arrValue.Kind() != reflect.Slice {
    52  		return -1
    53  	}
    54  
    55  	for i := 0; i < arrValue.Len(); i++ {
    56  		elem := arrValue.Index(i)
    57  
    58  		// Ensure the array element is a pointer
    59  		if elem.Kind() == reflect.Ptr {
    60  			// Dereference the pointer to get the underlying value
    61  			if valueValue.Kind() == reflect.Ptr && elem.Pointer() == valueValue.Pointer() {
    62  				return i
    63  			}
    64  			if elem.Elem().Interface() == valueValue.Interface() {
    65  				return i // Return the index if found
    66  			}
    67  		} else if elem.Kind() == reflect.Interface {
    68  			elem = elem.Elem()
    69  			if valueValue.Kind() == reflect.Ptr && elem.Interface() == valueValue.Pointer() {
    70  				return i
    71  			}
    72  			if elem.Interface() == valueValue.Interface() {
    73  				return i // Return the index if found
    74  			}
    75  		}
    76  	}
    77  
    78  	return -1 // Return -1 if not found
    79  }
    80  
    81  func handlePointer(elem reflect.Value) string {
    82  	if elem.IsNil() {
    83  		return "" // Skip nil pointers
    84  	}
    85  
    86  	// Dereference the pointer
    87  	elem = elem.Elem()
    88  	return handleValue(elem)
    89  }
    90  
    91  func handleValue(elem reflect.Value) string {
    92  	switch elem.Kind() {
    93  	case reflect.String:
    94  		return elem.String()
    95  	case reflect.Int:
    96  		return fmt.Sprintf("%d", elem.Interface())
    97  	case reflect.Float64:
    98  		return fmt.Sprintf("%f", elem.Interface())
    99  	case reflect.Bool:
   100  		return fmt.Sprintf("%t", elem.Interface())
   101  	default:
   102  		return "" // Skip unsupported types
   103  	}
   104  }
   105  
   106  func ArrJoin(arr interface{}, sep string) string {
   107  	var strSlice []string
   108  	var str string
   109  
   110  	arrValue := reflect.ValueOf(arr)
   111  
   112  	// Ensure arr is a slice
   113  	if arrValue.Kind() != reflect.Slice {
   114  		return ""
   115  	}
   116  
   117  	for i := 0; i < arrValue.Len(); i++ {
   118  		elem := arrValue.Index(i)
   119  
   120  		if elem.Kind() == reflect.Ptr {
   121  			str = handlePointer(elem)
   122  		} else if elem.Kind() == reflect.Interface {
   123  			str = handleValue(elem.Elem())
   124  		} else {
   125  			str = handleValue(elem)
   126  		}
   127  
   128  		if str != "" {
   129  			strSlice = append(strSlice, str)
   130  		}
   131  	}
   132  
   133  	return strings.Join(strSlice, sep)
   134  }
   135  
   136  // ArrShift removes the first element from the array
   137  func ArrShift(arr interface{}) interface{} {
   138  	arrValue := reflect.ValueOf(arr)
   139  
   140  	// Ensure arr is a pointer to a slice
   141  	if arrValue.Kind() != reflect.Ptr || arrValue.Elem().Kind() != reflect.Slice {
   142  		return nil
   143  	}
   144  
   145  	// Get the slice from the pointer
   146  	sliceValue := arrValue.Elem()
   147  
   148  	// Ensure the slice is not empty
   149  	if sliceValue.Len() == 0 {
   150  		return nil
   151  	}
   152  
   153  	// Get the first element
   154  	firstElem := sliceValue.Index(0)
   155  
   156  	// Create a new slice with one less element
   157  	newArrValue := reflect.MakeSlice(sliceValue.Type(), sliceValue.Len()-1, sliceValue.Cap())
   158  
   159  	// Copy the elements after the first one to the new slice
   160  	reflect.Copy(newArrValue, sliceValue.Slice(1, sliceValue.Len()))
   161  
   162  	// Set the original slice to the new slice
   163  	sliceValue.Set(newArrValue)
   164  
   165  	// Return the removed first element
   166  	return firstElem.Interface()
   167  }
   168  
   169  // ArrPop removes the last element from the array
   170  func ArrPop(arr interface{}) interface{} {
   171  	arrValue := reflect.ValueOf(arr)
   172  
   173  	// Ensure arr is a pointer to a slice
   174  	if arrValue.Kind() != reflect.Ptr || arrValue.Elem().Kind() != reflect.Slice {
   175  		return nil
   176  	}
   177  
   178  	// Get the slice from the pointer
   179  	sliceValue := arrValue.Elem()
   180  
   181  	// Ensure the slice is not empty
   182  	if sliceValue.Len() == 0 {
   183  		return nil
   184  	}
   185  
   186  	// Get the last element
   187  	lastIndex := sliceValue.Len() - 1
   188  	lastElem := sliceValue.Index(lastIndex)
   189  
   190  	// Create a new slice with one less element
   191  	newArrValue := reflect.MakeSlice(sliceValue.Type(), sliceValue.Len()-1, sliceValue.Cap()-1)
   192  
   193  	// Copy the elements before the last one to the new slice
   194  	reflect.Copy(newArrValue, sliceValue.Slice(0, lastIndex))
   195  
   196  	// Set the original slice to the new slice
   197  	sliceValue.Set(newArrValue)
   198  
   199  	// Return the removed last element
   200  	return lastElem.Interface()
   201  }
   202  
   203  // ArrUnshift adds an element to the beginning of the array
   204  func ArrUnshift(arr interface{}, value interface{}) int {
   205  	arrValue := reflect.ValueOf(arr)
   206  
   207  	// Ensure arr is a pointer to a slice
   208  	if arrValue.Kind() != reflect.Ptr || arrValue.Elem().Kind() != reflect.Slice {
   209  		return 0
   210  	}
   211  
   212  	// Get the slice from the pointer
   213  	sliceValue := arrValue.Elem()
   214  
   215  	// Create a new slice with one additional element
   216  	newArrValue := reflect.MakeSlice(sliceValue.Type(), sliceValue.Len()+1, sliceValue.Cap()+1)
   217  
   218  	// Set the new element as the first element
   219  	newArrValue.Index(0).Set(reflect.ValueOf(value))
   220  
   221  	// Copy the old elements to the new slice, starting at index 1
   222  	reflect.Copy(newArrValue.Slice(1, newArrValue.Len()), sliceValue)
   223  
   224  	// Set the original slice to the new slice
   225  	sliceValue.Set(newArrValue)
   226  
   227  	// Return the new length of the slice
   228  	return newArrValue.Len()
   229  }
   230  
   231  // ArrPush adds an element to the end of the array
   232  func ArrPush(arr interface{}, value interface{}) int {
   233  	arrValue := reflect.ValueOf(arr)
   234  
   235  	// Ensure arr is a pointer to a slice
   236  	if arrValue.Kind() != reflect.Ptr || arrValue.Elem().Kind() != reflect.Slice {
   237  		return 0
   238  	}
   239  
   240  	// Get the slice from the pointer
   241  	sliceValue := arrValue.Elem()
   242  
   243  	// Create a new slice with one additional element
   244  	newArrValue := reflect.MakeSlice(sliceValue.Type(), sliceValue.Len()+1, sliceValue.Cap()+1)
   245  
   246  	// Copy the old elements to the new slice
   247  	reflect.Copy(newArrValue, sliceValue)
   248  
   249  	// Set the new element as the last element
   250  	newArrValue.Index(sliceValue.Len()).Set(reflect.ValueOf(value))
   251  
   252  	// Set the original slice to the new slice
   253  	sliceValue.Set(newArrValue)
   254  
   255  	// Return the new length of the slice
   256  	return newArrValue.Len()
   257  }
   258  
   259  // ConcatArr concatenates two arrays
   260  func ConcatArr(arr1 interface{}, arr2 interface{}) interface{} {
   261  	var result []interface{}
   262  	value1 := reflect.ValueOf(arr1)
   263  	value2 := reflect.ValueOf(arr2)
   264  
   265  	// 检查 arr1 和 arr2 是否为切片
   266  	if value1.Kind() != reflect.Slice || value2.Kind() != reflect.Slice {
   267  		panic("ConcatArr: both inputs must be slices")
   268  	}
   269  
   270  	// 如果两个切片的类型相同
   271  	if value1.Type() == value2.Type() {
   272  		// 创建一个新的切片,类型与输入切片相同
   273  		result := reflect.MakeSlice(value1.Type(), 0, value1.Len()+value2.Len())
   274  
   275  		// 复制第一个切片的元素
   276  		for i := 0; i < value1.Len(); i++ {
   277  			result = reflect.Append(result, value1.Index(i))
   278  		}
   279  		// 复制第二个切片的元素
   280  		for i := 0; i < value2.Len(); i++ {
   281  			result = reflect.Append(result, value2.Index(i))
   282  		}
   283  		return result.Interface() // 返回类型相同的切片
   284  	}
   285  
   286  	// 否则返回 []interface{}
   287  	for i := 0; i < value1.Len(); i++ {
   288  		result = append(result, value1.Index(i).Interface())
   289  	}
   290  	for i := 0; i < value2.Len(); i++ {
   291  		result = append(result, value2.Index(i).Interface())
   292  	}
   293  	return result
   294  }
   295  
   296  // ArrAppend inserts a new pointer at a specified index in a pointer array.
   297  func ArrAppend(arr interface{}, value interface{}, index int) {
   298  	arrV := reflect.ValueOf(arr)
   299  	if arrV.Kind() != reflect.Ptr || arrV.Elem().Kind() != reflect.Slice {
   300  		return
   301  	}
   302  
   303  	sliceV := arrV.Elem()
   304  
   305  	if index < 0 || index > sliceV.Len() {
   306  		return
   307  	}
   308  
   309  	valueV := reflect.ValueOf(value)
   310  
   311  	// 创建一个容纳新值的切片
   312  	newSlice := reflect.Append(sliceV, reflect.Zero(sliceV.Type().Elem()))
   313  	reflect.Copy(newSlice.Slice(index+1, newSlice.Len()), newSlice.Slice(index, newSlice.Len()-1))
   314  	newSlice.Index(index).Set(valueV)
   315  
   316  	// 更新原始切片
   317  	sliceV.Set(newSlice)
   318  	return
   319  }
   320  
   321  // ArrRemove removes an element from the array
   322  func ArrRemove(arr interface{}, value interface{}) {
   323  	arrValue := reflect.ValueOf(arr)
   324  
   325  	// Ensure arr is a pointer to a slice
   326  	if arrValue.Kind() != reflect.Ptr || arrValue.Elem().Kind() != reflect.Slice {
   327  		return
   328  	}
   329  
   330  	// Get the slice from the pointer
   331  	slice := arrValue.Elem()
   332  	index := ArrIndex(slice.Interface(), value)
   333  	// If index is found, remove the element at that index
   334  	if index != -1 {
   335  		// Remove the element at the specified index
   336  		newSlice := reflect.MakeSlice(slice.Type(), 0, slice.Len()-1)
   337  
   338  		// Copy elements before the index
   339  		newSlice = reflect.AppendSlice(slice.Slice(0, index), slice.Slice(index+1, slice.Len()))
   340  		// Set the new slice back to the original reference
   341  		slice.Set(newSlice)
   342  	}
   343  }
   344  
   345  func SortArr(arr interface{}, order string) interface{} {
   346  	v := reflect.ValueOf(arr)
   347  	if v.Kind() != reflect.Slice {
   348  		panic("SortArr: input must be a slice")
   349  	}
   350  
   351  	// 创建一个新的切片来存储排序结果
   352  	newSlice := reflect.MakeSlice(v.Type(), v.Len(), v.Cap())
   353  	for i := 0; i < v.Len(); i++ {
   354  		newSlice.Index(i).Set(v.Index(i))
   355  	}
   356  
   357  	order = strings.ToLower(order)
   358  
   359  	sort.SliceStable(newSlice.Interface(), func(i, j int) bool {
   360  		return compare(newSlice.Index(i), newSlice.Index(j), order)
   361  	})
   362  
   363  	return newSlice.Interface()
   364  }
   365  
   366  func compare(elemI, elemJ reflect.Value, order string) bool {
   367  	valI := reflect.Indirect(elemI)
   368  	valJ := reflect.Indirect(elemJ)
   369  
   370  	// 对interface{}类型处理实际类型
   371  	if elemI.Kind() == reflect.Interface {
   372  		valI = reflect.Indirect(elemI.Elem())
   373  	}
   374  	if elemJ.Kind() == reflect.Interface {
   375  		valJ = reflect.Indirect(elemJ.Elem())
   376  	}
   377  
   378  	if valI.Kind() != valJ.Kind() {
   379  
   380  		if order == "asc" {
   381  			return valI.Kind() < valJ.Kind()
   382  		}
   383  		return valI.Kind() > valJ.Kind()
   384  
   385  	}
   386  
   387  	switch kind := valI.Kind(); kind {
   388  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   389  		return compareNumbers(valI.Int(), valJ.Int(), order)
   390  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   391  		return compareNumbers(int64(valI.Uint()), int64(valJ.Uint()), order)
   392  	case reflect.Float32, reflect.Float64:
   393  		return compareNumbers(valI.Float(), valJ.Float(), order)
   394  	case reflect.String:
   395  		return compareStrings(valI.String(), valJ.String(), order)
   396  	case reflect.Struct:
   397  		return compareStructs(valI, valJ, order)
   398  	default:
   399  		panic("SortArr: unsupported element type")
   400  	}
   401  }
   402  
   403  func compareNumbers(a, b interface{}, order string) bool {
   404  	switch order {
   405  	case "asc":
   406  		return a.(int64) < b.(int64)
   407  	case "desc":
   408  		return a.(int64) > b.(int64)
   409  	default:
   410  		return a.(int64) > b.(int64)
   411  	}
   412  }
   413  
   414  func compareStrings(a, b string, order string) bool {
   415  	switch order {
   416  	case "asc":
   417  		return a < b
   418  	case "desc":
   419  		return a > b
   420  	default:
   421  		return a > b
   422  	}
   423  }
   424  
   425  func compareStructs(valI, valJ reflect.Value, order string) bool {
   426  	if valI.NumField() > 0 && valJ.NumField() > 0 {
   427  		fieldI := reflect.Indirect(valI.Field(0))
   428  		fieldJ := reflect.Indirect(valJ.Field(0))
   429  		if fieldI.Kind() == fieldJ.Kind() {
   430  			switch fieldI.Kind() {
   431  			case reflect.String:
   432  				return compareStrings(fieldI.String(), fieldJ.String(), order)
   433  			case reflect.Int:
   434  				return compareNumbers(fieldI.Int(), fieldJ.Int(), order)
   435  			}
   436  		}
   437  	}
   438  	return false
   439  }