maputils.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. package maputils
  2. import (
  3. "github.com/pkg/errors"
  4. "strconv"
  5. "strings"
  6. )
  7. const (
  8. pathSeparator = "."
  9. )
  10. // GetValueByPath 通过路径查询map的值,常用查找unmarshal到map的json或者yaml中的值
  11. // 参数:
  12. // m: key是string类型的map,值可以是任意类型,如果map下的值还是map,则map的key必须为string类型
  13. // path: 路径,如foo1.foo1_sub.[0],key为foo1的值是一个map[string]any,foo1_sub对应的值是一个slice,如果需要取slice的某一个值,可以用[n]获取
  14. // 返回值:
  15. // 对应的值和错误
  16. func GetValueByPath(m map[string]any, path string) (any, error) {
  17. if m == nil || strings.TrimSpace(path) == "" {
  18. return nil, errors.New("没有传递需要查找的数据或路径")
  19. }
  20. var retValue any
  21. var currentFind any
  22. currentFind = m
  23. pathParts := strings.Split(path, pathSeparator)
  24. for _, pathPart := range pathParts {
  25. if strings.HasPrefix(pathPart, "[") && strings.HasSuffix(pathPart, "]") {
  26. indexStr := strings.TrimLeft(strings.TrimRight(pathPart, "]"), "[")
  27. index, err := strconv.Atoi(strings.Trim(indexStr, " "))
  28. if err != nil {
  29. return nil, err
  30. }
  31. findSlice, ok := currentFind.([]any)
  32. if ok {
  33. if index > len(findSlice)-1 {
  34. retValue = nil
  35. } else {
  36. retValue = findSlice[index]
  37. }
  38. } else {
  39. findMapSlice, ok := currentFind.([]map[string]any)
  40. if !ok {
  41. return nil, errors.New("对应slice路径的值不是slice: " + pathPart)
  42. }
  43. if index > len(findMapSlice)-1 {
  44. retValue = nil
  45. } else {
  46. retValue = findMapSlice[index]
  47. }
  48. }
  49. } else {
  50. findMap, ok := currentFind.(map[string]any)
  51. if !ok {
  52. return nil, errors.New("对应map路径的值不是map[string]any: " + pathPart)
  53. }
  54. value, ok := findMap[pathPart]
  55. if !ok {
  56. return nil, nil
  57. }
  58. retValue = value
  59. }
  60. if retValue == nil {
  61. return nil, nil
  62. }
  63. currentFind = retValue
  64. }
  65. return retValue, nil
  66. }
  67. // GetValueByKey 通过key查询map的值
  68. // 模板参数:
  69. // K是map的key的类型,V是map值的类型
  70. // 参数:
  71. // m: 从这个map获取值
  72. // key: map的key
  73. // 返回值:
  74. // 对应的值和获取是否成功,失败可能有两个原因:对应的key不存在或者V类型转换失败
  75. func GetValueByKey[K comparable, V any](m map[K]any, key K) (V, bool) {
  76. var zeroValue V
  77. mapValue, ok := m[key]
  78. if !ok {
  79. return zeroValue, false
  80. }
  81. v, ok := mapValue.(V)
  82. if !ok {
  83. return zeroValue, false
  84. }
  85. return v, true
  86. }
  87. // SortMap 可以排序的map
  88. // 模板参数:
  89. // K是map的key的类型,V是map值的类型
  90. type SortMap[K comparable, V any] struct {
  91. sortedKeys []K
  92. m map[K]V
  93. }
  94. // Range 遍历排序后的map
  95. // 模板参数:
  96. // K是map的key的类型,V是map值的类型
  97. // 参数:
  98. // callback: 遍历回调
  99. func (sortMap *SortMap[K, V]) Range(callback func(index int, key K, value V)) {
  100. if callback != nil {
  101. for i, key := range sortMap.sortedKeys {
  102. callback(i, key, sortMap.m[key])
  103. }
  104. }
  105. }
  106. // Sort 排序map
  107. // 模板参数:
  108. // K是map的key的类型,V是map值的类型
  109. // 参数:
  110. // m: 需要排序的map
  111. // sortKeysFunc: 对key进行排序的回调函数
  112. // 返回值:
  113. // SortMap指针,之后可以调用Range遍历排序后的map
  114. func Sort[K comparable, V any](m map[K]V, sortKeysFunc func(keys []K)) *SortMap[K, V] {
  115. keys := make([]K, 0)
  116. for key := range m {
  117. keys = append(keys, key)
  118. }
  119. if sortKeysFunc != nil {
  120. sortKeysFunc(keys)
  121. }
  122. return &SortMap[K, V]{
  123. sortedKeys: keys,
  124. m: m,
  125. }
  126. }