go语言map排序实现(一劳永逸)

我们在日常开发中,或多或少会经常需要对 map 进行排序,这里就带大家实现对 map 排序的封装

  • 调用简单,使用方便
  • 支持对 int int8 int16 int32 int64 float64 float32 string 作为 keymap 进行排序遍历

思路

通常我们对 map 进行排序都是先将 key 存储到一个 slice 中,之后对其进行排序操作,但是封装起来会遇到以各种类型作为 keyvaluemap ,这种情况我们按照如下方法来克服

  • 声明一个拥有两个入参的函数,用来完成我们的操作,即 func EachMap(eachMap interface{}, eachFunc interface{})
  • eachMap :传入 map ,因为是 interface{} ,所以只要是map都能够传入
  • eachFunc :接收 mapkeyvalue 的函数,需要包含两个入参,类型要与 mapkeyvalue 完全一致
  • 最后利用golang的反射就可以完成这个功能。

代码如下

源码地址: https://gitee.com/xusixxxx/bug-research-laboratory/tree/master/kercylan-core/utils/ksort

// 以map的key(int\float\string)排序遍历map
// eachMap      ->  待遍历的map
// eachFunc     ->  map遍历接收,入参应该符合map的key和value
// 需要对传入类型进行检查,不符合则直接panic提醒进行代码调整
func EachMap(eachMap interface{}, eachFunc interface{})  {
    eachMapValue := reflect.ValueOf(eachMap)
    eachFuncValue := reflect.ValueOf(eachFunc)
    eachMapType := eachMapValue.Type()
    eachFuncType := eachFuncValue.Type()
    if eachMapValue.Kind() != reflect.Map {
        panic(errors.New("ksort.EachMap failed. parameter \"eachMap\" type must is map[...]...{}"))
    }
    if eachFuncValue.Kind() != reflect.Func {
        panic(errors.New("ksort.EachMap failed. parameter \"eachFunc\" type must is func(key ..., value ...)"))
    }
    if eachFuncType.NumIn() != 2 {
        panic(errors.New("ksort.EachMap failed. \"eachFunc\" input parameter count must is 2"))
    }
    if eachFuncType.In(0).Kind() != eachMapType.Key().Kind() {
        panic(errors.New("ksort.EachMap failed. \"eachFunc\" input parameter 1 type not equal of \"eachMap\" key"))
    }
    if eachFuncType.In(1).Kind() != eachMapType.Elem().Kind() {
        panic(errors.New("ksort.EachMap failed. \"eachFunc\" input parameter 2 type not equal of \"eachMap\" value"))
    }

    // 对key进行排序
    // 获取排序后map的key和value,作为参数调用eachFunc即可
    switch eachMapType.Key().Kind() {
    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
        keys := make([]int, 0)
        keysMap := map[int]reflect.Value{}
        for _, value := range eachMapValue.MapKeys() {
            keys = append(keys, int(value.Int()))
            keysMap[int(value.Int())] = value
        }
        sort.Ints(keys)
        for _, key := range keys {
            eachFuncValue.Call([]reflect.Value{keysMap[key], eachMapValue.MapIndex(keysMap[key])})
        }
    case reflect.Float64, reflect.Float32:
        keys := make([]float64, 0)
        keysMap := map[float64]reflect.Value{}
        for _, value := range eachMapValue.MapKeys() {
            keys = append(keys, float64(value.Float()))
            keysMap[float64(value.Float())] = value
        }
        sort.Float64s(keys)
        for _, key := range keys {
            eachFuncValue.Call([]reflect.Value{keysMap[key], eachMapValue.MapIndex(keysMap[key])})
        }
    case reflect.String:
        keys := make([]string, 0)
        keysMap := map[string]reflect.Value{}
        for _, value := range eachMapValue.MapKeys() {
            keys = append(keys, value.String())
            keysMap[value.String()] = value
        }
        sort.Strings(keys)
        for _, key := range keys {
            eachFuncValue.Call([]reflect.Value{keysMap[key], eachMapValue.MapIndex(keysMap[key])})
        }
    default:
        panic(errors.New("\"eachMap\" key type must is int or float or string"))
    }
}

使用

func main() {
    m := map[int]string{}
    m[5] = "Hello World"
    m[2] = "Hello World"
    m[1] = "Hello World"
    m[3] = "Hello World"
    m[4] = "Hello World"
    
    EachMap(m, func(key int, value string) {
        fmt.Println(key, value)
    })
}
我来评几句
登录后评论

已发表评论数()

相关站点

热门文章