Golang中如何按值对Map进行排序
Golang中如何按值对Map进行排序 我在Stackoverflow上找到了这个五年前的答案。
这仍然是目前最好的方法吗?还是现在有更好的(所谓更好,我指的是需要更少代码的替代方案)方式来实现这个?
package main
import (
"fmt"
"sort"
)
func main() {
m := map[string]int{
"something": 10,
"yo": 20,
"blah": 20,
}
type kv struct {
Key string
Value int
}
var ss []kv
for k, v := range m {
ss = append(ss, kv{k, v})
}
sort.Slice(ss, func(i, j int) bool {
return ss[i].Value > ss[j].Value
})
for _, kv := range ss {
fmt.Printf("%s, %d\n", kv.Key, kv.Value)
}
}
来源:sorting - How can I sort a Map[string]int by its values? - Stack Overflow
更多关于Golang中如何按值对Map进行排序的实战教程也可以访问 https://www.itying.com/category-94-b0.html
4 回复
更多关于Golang中如何按值对Map进行排序的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我想省略 struct。
我发现了一种方法,可以避免使用结构体:排序 - 如何按值对 Map[string]int 进行排序? - Stack Overflow
确实,这个版本大约缩短了20%。
在此发布Stack Overflow上的解决方案以供参考:
func main() {
counts := map[string]int{"hello": 10, "foo": 20, "bar": 20}
keys := make([]string, 0, len(counts))
for key := range counts {
keys = append(keys, key)
}
sort.Slice(keys, func(i, j int) bool { return counts[keys[i]] > counts[keys[j]] })
for _, key := range keys {
fmt.Printf("%s, %d\n", key, counts[key])
}
}
在Go中按值对Map排序,目前仍然推荐使用你找到的方法。虽然Go语言本身没有内置Map排序功能,但这种方法通过将键值对转换为切片再进行排序,是标准且高效的做法。
以下是当前Go 1.21中的实现示例:
package main
import (
"fmt"
"slices"
)
func main() {
m := map[string]int{
"something": 10,
"yo": 20,
"blah": 20,
"test": 15,
}
// 使用泛型切片和slices.SortFunc(Go 1.21+)
type Pair struct {
Key string
Value int
}
pairs := make([]Pair, 0, len(m))
for k, v := range m {
pairs = append(pairs, Pair{k, v})
}
// 使用slices.SortFunc按值降序排序
slices.SortFunc(pairs, func(a, b Pair) int {
if a.Value > b.Value {
return -1 // 降序
}
if a.Value < b.Value {
return 1
}
return 0
})
// 或者按值升序排序
slices.SortFunc(pairs, func(a, b Pair) int {
return a.Value - b.Value // 升序
})
for _, p := range pairs {
fmt.Printf("%s: %d\n", p.Key, p.Value)
}
}
如果你需要保持与旧版本Go的兼容性,可以使用传统的sort.Slice方法:
package main
import (
"fmt"
"sort"
)
func main() {
m := map[string]int{
"something": 10,
"yo": 20,
"blah": 20,
}
// 更简洁的结构体定义
pairs := make([]struct {
Key string
Value int
}, 0, len(m))
for k, v := range m {
pairs = append(pairs, struct {
Key string
Value int
}{k, v})
}
// 按值降序排序
sort.Slice(pairs, func(i, j int) bool {
if pairs[i].Value == pairs[j].Value {
return pairs[i].Key < pairs[j].Key // 值相同时按键排序
}
return pairs[i].Value > pairs[j].Value
})
for _, p := range pairs {
fmt.Printf("%s: %d\n", p.Key, p.Value)
}
}
对于需要频繁排序的场景,可以考虑封装为通用函数:
func SortMapByValue[K comparable, V constraints.Ordered](m map[K]V, descending bool) []struct {
Key K
Value V
} {
pairs := make([]struct {
Key K
Value V
}, 0, len(m))
for k, v := range m {
pairs = append(pairs, struct {
Key K
Value V
}{k, v})
}
sort.Slice(pairs, func(i, j int) bool {
if descending {
return pairs[i].Value > pairs[j].Value
}
return pairs[i].Value < pairs[j].Value
})
return pairs
}
这些方法在性能上都是最优的,时间复杂度为O(n log n),其中n是Map的大小。

