Go语言如何像foreach一样有序遍历map

问题

Go语言的Map是无序遍历的,遍历一个map代码如下

package main

import (
    "fmt"
)

func main() {
    m := map[string]int{"Apple": 20, "Tomato": 12, "Banana": 18}
    for k, v := range m {
        fmt.Println(k, v)
    }
}

我们来运行3次

可以看到每次都是随机的,如何给一个map进行排序,并根据我们的的key进行遍历呢?
比如我们要跟据字典顺序来输出map的内容,怎么办?

解决

排序思路

其实我们可以借助一个slice来保存map的key,通过遍历排序后的slice来达到根据keys遍历map的效果

package main

import (
    "fmt"
    "sort"
)

func main() {
    m := map[string]int{"Apple": 20, "Tomato": 12, "Banana": 18}
    //给key排序一下
    keys := make([]string, 0, len(m))
    for k := range m {
        keys = append(keys, k)
    }
    sort.Strings(keys)

    //再次遍历
    for _, k := range keys {
        fmt.Println(k, m[k])
    }
}

再次运行如下,可以看到结果都是一致的

现在这个虽然可以达到给key排序,但是有一个弊端,就是不能像php中的foreach一样有序的遍历
比如如下的php中的foreach代码,永远是按照添加的顺序输出的

<?php
$map = [
    "a" => 1,
    "b" => 2,
    "d" => 3,
    "c" => 4,
];
foreach ($map as $k => $v) {
    echo "{$k}={$v}" . PHP_EOL;
}

运行结果如下

开源实现

我们知道上面的永远会根据a,b,c,d这样keys的顺序来输出,不满足我们的要求。
好在已经有人实现了有序Map,下载地址:这是一个链接 elliotchance/orderedmap

我们来使用一下

package main

import (
    "fmt"
    "github.com/elliotchance/orderedmap"
)

func main() {
    //新建一个order map
    m := orderedmap.NewOrderedMap()
    m.Set("a", 1)
    m.Set("b", 2)
    m.Set("d", 3)
    m.Set("c", 4)
    //遍历一下
    for _, key := range m.Keys() {
        value, _ := m.Get(key)
        fmt.Printf("%v=%v\n", key, value)
    }
}

运行结果如下

这个包可以让我们像php的foreach一样high起来,真的是绝了!
以上内容由chenqionghe倾情提供,are you ok?

posted @ 2020-11-10 22:23  雪山飞猪  阅读(7255)  评论(3编辑  收藏  举报