如何从Golang的地图中提取x个最上面的int值?

时间:2018-09-26 09:50:05

标签: sorting dictionary go

我有一个map[string]int

我想从中获取x个顶部值并将它们存储在另一个数据结构,另一个映射或切片中。 从https://blog.golang.org/go-maps-in-action#TOC_7.我了解到:

  

在具有范围循环的地图上进行迭代时,迭代顺序为   未指定,并且一次迭代不能保证相同   到下一个。

所以结果结构将是一个切片。

我看了几个相关主题,但是没有一个适合我的问题:

related topic 1

related topic 2

related topic 3

请问最有效的方法是什么?

谢谢

编辑: 我的解决方案是将地图切成薄片并进行排序,然后提取第一个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值,那么根据我的解决方案,我将不得不再次将切片变成地图。这仍然是最有效的方法吗?

1 个答案:

答案 0 :(得分:3)

创建切片和排序是一个很好的解决方案;但是,您也可以使用heap。两种实现方式的Big O性能均应相同(n log n),因此这是一个可行的替代方案,其优点是,如果您要添加新条目,则仍然可以有效地访问前N个项目,而无需重复对整个集合进行排序。

要使用堆,您可以使用kv函数将Less类型的heap.Interface实现为{em> ({{1 }}),添加地图中的所有条目,然后弹出要使用的项目数。

例如(Go Playground):

h[i].Value > h[j].Value