gutil_slice.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. package gutil
  7. import (
  8. "github.com/gogf/gf/util/gconv"
  9. "reflect"
  10. )
  11. // SliceCopy does a shallow copy of slice `data` for most commonly used slice type
  12. // []interface{}.
  13. func SliceCopy(data []interface{}) []interface{} {
  14. newData := make([]interface{}, len(data))
  15. copy(newData, data)
  16. return newData
  17. }
  18. // SliceDelete deletes an element at `index` and returns the new slice.
  19. // It does nothing if the given `index` is invalid.
  20. func SliceDelete(data []interface{}, index int) (newSlice []interface{}) {
  21. if index < 0 || index >= len(data) {
  22. return data
  23. }
  24. // Determine array boundaries when deleting to improve deletion efficiency.
  25. if index == 0 {
  26. return data[1:]
  27. } else if index == len(data)-1 {
  28. return data[:index]
  29. }
  30. // If it is a non-boundary delete,
  31. // it will involve the creation of an array,
  32. // then the deletion is less efficient.
  33. return append(data[:index], data[index+1:]...)
  34. }
  35. // SliceToMap converts slice type variable `slice` to `map[string]interface{}`.
  36. // Note that if the length of `slice` is not an even number, it returns nil.
  37. // Eg:
  38. // ["K1", "v1", "K2", "v2"] => {"K1": "v1", "K2": "v2"}
  39. // ["K1", "v1", "K2"] => nil
  40. func SliceToMap(slice interface{}) map[string]interface{} {
  41. var (
  42. reflectValue = reflect.ValueOf(slice)
  43. reflectKind = reflectValue.Kind()
  44. )
  45. for reflectKind == reflect.Ptr {
  46. reflectValue = reflectValue.Elem()
  47. reflectKind = reflectValue.Kind()
  48. }
  49. switch reflectKind {
  50. case reflect.Slice, reflect.Array:
  51. length := reflectValue.Len()
  52. if length%2 != 0 {
  53. return nil
  54. }
  55. data := make(map[string]interface{})
  56. for i := 0; i < reflectValue.Len(); i += 2 {
  57. data[gconv.String(reflectValue.Index(i).Interface())] = reflectValue.Index(i + 1).Interface()
  58. }
  59. return data
  60. }
  61. return nil
  62. }
  63. // SliceToMapWithColumnAsKey converts slice type variable `slice` to `map[interface{}]interface{}`
  64. // The value of specified column use as the key for returned map.
  65. // Eg:
  66. // SliceToMapWithColumnAsKey([{"K1": "v1", "K2": 1}, {"K1": "v2", "K2": 2}], "K1") => {"v1": {"K1": "v1", "K2": 1}, "v2": {"K1": "v2", "K2": 2}}
  67. // SliceToMapWithColumnAsKey([{"K1": "v1", "K2": 1}, {"K1": "v2", "K2": 2}], "K2") => {1: {"K1": "v1", "K2": 1}, 2: {"K1": "v2", "K2": 2}}
  68. func SliceToMapWithColumnAsKey(slice interface{}, key interface{}) map[interface{}]interface{} {
  69. var (
  70. reflectValue = reflect.ValueOf(slice)
  71. reflectKind = reflectValue.Kind()
  72. )
  73. for reflectKind == reflect.Ptr {
  74. reflectValue = reflectValue.Elem()
  75. reflectKind = reflectValue.Kind()
  76. }
  77. data := make(map[interface{}]interface{})
  78. switch reflectKind {
  79. case reflect.Slice, reflect.Array:
  80. for i := 0; i < reflectValue.Len(); i++ {
  81. if k, ok := ItemValue(reflectValue.Index(i), key); ok {
  82. data[k] = reflectValue.Index(i).Interface()
  83. }
  84. }
  85. }
  86. return data
  87. }