123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- package maputils
- import (
- "github.com/pkg/errors"
- "strconv"
- "strings"
- )
- const (
- pathSeparator = "."
- )
- // GetValueByPath 通过路径查询map的值,常用查找unmarshal到map的json或者yaml中的值
- // 参数:
- // m: key是string类型的map,值可以是任意类型,如果map下的值还是map,则map的key必须为string类型
- // path: 路径,如foo1.foo1_sub.[0],key为foo1的值是一个map[string]any,foo1_sub对应的值是一个slice,如果需要取slice的某一个值,可以用[n]获取
- // 返回值:
- // 对应的值和错误
- func GetValueByPath(m map[string]any, path string) (any, error) {
- if m == nil || strings.TrimSpace(path) == "" {
- return nil, errors.New("没有传递需要查找的数据或路径")
- }
- var retValue any
- var currentFind any
- currentFind = m
- pathParts := strings.Split(path, pathSeparator)
- for _, pathPart := range pathParts {
- if strings.HasPrefix(pathPart, "[") && strings.HasSuffix(pathPart, "]") {
- indexStr := strings.TrimLeft(strings.TrimRight(pathPart, "]"), "[")
- index, err := strconv.Atoi(strings.Trim(indexStr, " "))
- if err != nil {
- return nil, err
- }
- findSlice, ok := currentFind.([]any)
- if ok {
- if index > len(findSlice)-1 {
- retValue = nil
- } else {
- retValue = findSlice[index]
- }
- } else {
- findMapSlice, ok := currentFind.([]map[string]any)
- if !ok {
- return nil, errors.New("对应slice路径的值不是slice: " + pathPart)
- }
- if index > len(findMapSlice)-1 {
- retValue = nil
- } else {
- retValue = findMapSlice[index]
- }
- }
- } else {
- findMap, ok := currentFind.(map[string]any)
- if !ok {
- return nil, errors.New("对应map路径的值不是map[string]any: " + pathPart)
- }
- value, ok := findMap[pathPart]
- if !ok {
- return nil, nil
- }
- retValue = value
- }
- if retValue == nil {
- return nil, nil
- }
- currentFind = retValue
- }
- return retValue, nil
- }
- // GetValueByKey 通过key查询map的值
- // 模板参数:
- // K是map的key的类型,V是map值的类型
- // 参数:
- // m: 从这个map获取值
- // key: map的key
- // 返回值:
- // 对应的值和获取是否成功,失败可能有两个原因:对应的key不存在或者V类型转换失败
- func GetValueByKey[K comparable, V any](m map[K]any, key K) (V, bool) {
- var zeroValue V
- mapValue, ok := m[key]
- if !ok {
- return zeroValue, false
- }
- v, ok := mapValue.(V)
- if !ok {
- return zeroValue, false
- }
- return v, true
- }
- // SortMap 可以排序的map
- // 模板参数:
- // K是map的key的类型,V是map值的类型
- type SortMap[K comparable, V any] struct {
- sortedKeys []K
- m map[K]V
- }
- // Range 遍历排序后的map
- // 模板参数:
- // K是map的key的类型,V是map值的类型
- // 参数:
- // callback: 遍历回调
- func (sortMap *SortMap[K, V]) Range(callback func(index int, key K, value V)) {
- if callback != nil {
- for i, key := range sortMap.sortedKeys {
- callback(i, key, sortMap.m[key])
- }
- }
- }
- // Sort 排序map
- // 模板参数:
- // K是map的key的类型,V是map值的类型
- // 参数:
- // m: 需要排序的map
- // sortKeysFunc: 对key进行排序的回调函数
- // 返回值:
- // SortMap指针,之后可以调用Range遍历排序后的map
- func Sort[K comparable, V any](m map[K]V, sortKeysFunc func(keys []K)) *SortMap[K, V] {
- keys := make([]K, 0)
- for key := range m {
- keys = append(keys, key)
- }
- if sortKeysFunc != nil {
- sortKeysFunc(keys)
- }
- return &SortMap[K, V]{
- sortedKeys: keys,
- m: m,
- }
- }
|