我有一个map[string]int
我想从中获取x个顶部值并将它们存储在另一个数据结构,另一个映射或切片中。 从https://blog.golang.org/go-maps-in-action#TOC_7.我了解到:
在具有范围循环的地图上进行迭代时,迭代顺序为 未指定,并且一次迭代不能保证相同 到下一个。
所以结果结构将是一个切片。
我看了几个相关主题,但是没有一个适合我的问题:
请问最有效的方法是什么?
谢谢
编辑:
我的解决方案是将地图切成薄片并进行排序,然后提取第一个x值。
但是有更好的方法吗?
package main
import (
"fmt"
"sort"
)
func main() {
// I want the x top values
x := 3
// Here is the map
m := make(map[string]int)
m["k1"] = 7
m["k2"] = 31
m["k3"] = 24
m["k4"] = 13
m["k5"] = 31
m["k6"] = 12
m["k7"] = 25
m["k8"] = -8
m["k9"] = -76
m["k10"] = 22
m["k11"] = 76
// Turning the map into this structure
type kv struct {
Key string
Value int
}
var ss []kv
for k, v := range m {
ss = append(ss, kv{k, v})
}
// Then sorting the slice by value, higher first.
sort.Slice(ss, func(i, j int) bool {
return ss[i].Value > ss[j].Value
})
// Print the x top values
for _, kv := range ss[:x] {
fmt.Printf("%s, %d\n", kv.Key, kv.Value)
}
}
Link to golang playground example
如果我想在地图的末尾有x个top值,那么根据我的解决方案,我将不得不再次将切片变成地图。这仍然是最有效的方法吗?
答案 0 :(得分:3)
创建切片和排序是一个很好的解决方案;但是,您也可以使用heap。两种实现方式的Big O性能均应相同(n log n),因此这是一个可行的替代方案,其优点是,如果您要添加新条目,则仍然可以有效地访问前N个项目,而无需重复对整个集合进行排序。>
要使用堆,您可以使用kv
函数将Less
类型的heap.Interface
实现为{em> ({{1 }}),添加地图中的所有条目,然后弹出要使用的项目数。
例如(Go Playground):
h[i].Value > h[j].Value