はじめに
Goのmapは順序を保持しないため、並び替えたい場合はひと工夫が必要です。
以下のようなマップをキー・バリューそれぞれで昇順・降順に並べ替えていきます。
m := map[string]int{
"Taro": 23,
"Keiko": 41,
"Jun": 11,
"Azusa": 16,
}
// マップは順序を保持しない
for k, v := range m {
fmt.Printf("Name: %s, Age: %d\n", k, v)
}
キー(文字列)でソートする
昇順
// 先にキーだけソート
keys := []string{}
for k := range m {
keys = append(keys, k)
}
// ソート(昇順)
sort.Strings(keys)
// もう一度for-rangeを使い、順に値を取り出す
for _, k := range keys {
fmt.Printf("Name: %s, Age: %d\n", k, m[k])
}
降順
// 先にキーだけソート
keys := []string{}
for k := range m {
keys = append(keys, k)
}
// ソート(降順)
sort.Sort(sort.Reverse(sort.StringSlice(keys)))
// もう一度for-rangeを使い、順に値を取り出す
for _, k := range keys {
fmt.Printf("Name: %s, Age: %d\n", k, m[k])
}
バリュー(Int)でソートする
昇順
// 先にバリューだけソート
values := []int{}
for _, v := range m {
values = append(values, v)
}
// ソート(昇順)
sort.Ints(values)
// valuesが小さい順になっているので、マップのバリューと比較し順に値を取り出す
for _, v := range values {
for mk, mv := range m {
if v == mv {
fmt.Printf("Name: %s, Age: %d\n", mk, mv)
}
}
}
降順
// 先にバリューだけソート
values := []int{}
for _, v := range m {
values = append(values, v)
}
// ソート(降順)
sort.Sort(sort.Reverse(sort.IntSlice(values)))
// valuesが小さい順になっているので、マップのバリューと比較し順に値を取り出す
for _, v := range values {
for mk, mv := range m {
if v == mv {
fmt.Printf("Name: %s, Age: %d\n", mk, mv)
}
}
}
サンプルコード
サンプルコード全体
package main
import (
"fmt"
"sort"
)
func main() {
m := map[string]int{
"Taro": 23,
"Keiko": 41,
"Jun": 11,
"Azusa": 16,
}
// mapは順序を保持しない
fmt.Println("初期状態 -------------------------------------")
for k, v := range m {
fmt.Printf("Name: %s, Age: %d\n", k, v)
}
fmt.Println("キーでソート -------------------------------------")
// 先にキーだけソート
keys := []string{}
for k := range m {
keys = append(keys, k)
}
// ソート
// 昇順
sort.Strings(keys)
// 降順
// sort.Sort(sort.Reverse(sort.StringSlice(keys)))
// もう一度for-rangeでソートされた順に値を取り出す
for _, k := range keys {
fmt.Printf("Name: %s, Age: %d\n", k, m[k])
}
// バリューでソートしたい場合 -------------------------------------
fmt.Println("バリューでソート -------------------------------------")
// 先にバリューだけソート
values := []int{}
for _, v := range m {
values = append(values, v)
}
// ソート
// 昇順
sort.Ints(values)
// 降順
// sort.Sort(sort.Reverse(sort.IntSlice(values)))
// valuesが小さい順になっているので、マップのバリューと比較し順に値を取り出す
for _, v := range values {
for mk, mv := range m {
if v == mv {
fmt.Printf("Name: %s, Age: %d\n", mk, mv)
}
}
}
}
終わりに
やはりひと手間かかって少し面倒ですね......もっと良い方法があったらぜひ教えてください。
参考