gutil_slice.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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. "reflect"
  9. "github.com/gogf/gf/v2/util/gconv"
  10. )
  11. // SliceCopy does a shallow copy of slice `data` for most commonly used slice type
  12. // []interface{}.
  13. func SliceCopy(slice []interface{}) []interface{} {
  14. newSlice := make([]interface{}, len(slice))
  15. copy(newSlice, slice)
  16. return newSlice
  17. }
  18. // SliceInsertBefore inserts the `values` to the front of `index` and returns a new slice.
  19. func SliceInsertBefore(slice []interface{}, index int, values ...interface{}) (newSlice []interface{}) {
  20. if index < 0 || index >= len(slice) {
  21. return slice
  22. }
  23. newSlice = make([]interface{}, len(slice)+len(values))
  24. copy(newSlice, slice[0:index])
  25. copy(newSlice[index:], values)
  26. copy(newSlice[index+len(values):], slice[index:])
  27. return
  28. }
  29. // SliceInsertAfter inserts the `values` to the back of `index` and returns a new slice.
  30. func SliceInsertAfter(slice []interface{}, index int, values ...interface{}) (newSlice []interface{}) {
  31. if index < 0 || index >= len(slice) {
  32. return slice
  33. }
  34. newSlice = make([]interface{}, len(slice)+len(values))
  35. copy(newSlice, slice[0:index+1])
  36. copy(newSlice[index+1:], values)
  37. copy(newSlice[index+1+len(values):], slice[index+1:])
  38. return
  39. }
  40. // SliceDelete deletes an element at `index` and returns the new slice.
  41. // It does nothing if the given `index` is invalid.
  42. func SliceDelete(slice []interface{}, index int) (newSlice []interface{}) {
  43. if index < 0 || index >= len(slice) {
  44. return slice
  45. }
  46. // Determine array boundaries when deleting to improve deletion efficiency.
  47. if index == 0 {
  48. return slice[1:]
  49. } else if index == len(slice)-1 {
  50. return slice[:index]
  51. }
  52. // If it is a non-boundary delete,
  53. // it will involve the creation of an array,
  54. // then the deletion is less efficient.
  55. return append(slice[:index], slice[index+1:]...)
  56. }
  57. // SliceToMap converts slice type variable `slice` to `map[string]interface{}`.
  58. // Note that if the length of `slice` is not an even number, it returns nil.
  59. // Eg:
  60. // ["K1", "v1", "K2", "v2"] => {"K1": "v1", "K2": "v2"}
  61. // ["K1", "v1", "K2"] => nil
  62. func SliceToMap(slice interface{}) map[string]interface{} {
  63. var (
  64. reflectValue = reflect.ValueOf(slice)
  65. reflectKind = reflectValue.Kind()
  66. )
  67. for reflectKind == reflect.Ptr {
  68. reflectValue = reflectValue.Elem()
  69. reflectKind = reflectValue.Kind()
  70. }
  71. switch reflectKind {
  72. case reflect.Slice, reflect.Array:
  73. length := reflectValue.Len()
  74. if length%2 != 0 {
  75. return nil
  76. }
  77. data := make(map[string]interface{})
  78. for i := 0; i < reflectValue.Len(); i += 2 {
  79. data[gconv.String(reflectValue.Index(i).Interface())] = reflectValue.Index(i + 1).Interface()
  80. }
  81. return data
  82. }
  83. return nil
  84. }
  85. // SliceToMapWithColumnAsKey converts slice type variable `slice` to `map[interface{}]interface{}`
  86. // The value of specified column use as the key for returned map.
  87. // Eg:
  88. // SliceToMapWithColumnAsKey([{"K1": "v1", "K2": 1}, {"K1": "v2", "K2": 2}], "K1") => {"v1": {"K1": "v1", "K2": 1}, "v2": {"K1": "v2", "K2": 2}}
  89. // SliceToMapWithColumnAsKey([{"K1": "v1", "K2": 1}, {"K1": "v2", "K2": 2}], "K2") => {1: {"K1": "v1", "K2": 1}, 2: {"K1": "v2", "K2": 2}}
  90. func SliceToMapWithColumnAsKey(slice interface{}, key interface{}) map[interface{}]interface{} {
  91. var (
  92. reflectValue = reflect.ValueOf(slice)
  93. reflectKind = reflectValue.Kind()
  94. )
  95. for reflectKind == reflect.Ptr {
  96. reflectValue = reflectValue.Elem()
  97. reflectKind = reflectValue.Kind()
  98. }
  99. data := make(map[interface{}]interface{})
  100. switch reflectKind {
  101. case reflect.Slice, reflect.Array:
  102. for i := 0; i < reflectValue.Len(); i++ {
  103. if k, ok := ItemValue(reflectValue.Index(i), key); ok {
  104. data[k] = reflectValue.Index(i).Interface()
  105. }
  106. }
  107. }
  108. return data
  109. }