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 }