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?

Tags: