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

KercyLan · · 1899 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

我们在日常开发中,或多或少会经常需要对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)
    })
}

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:KercyLan

查看原文:go语言map排序实现(一劳永逸)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1899 次点击  
加入收藏 微博
1 回复  |  直到 2019-12-11 11:02:51
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传