dongzhang0418 2017-08-30 15:11
浏览 24
已采纳

如何使用不同的数据结构递归遍历地图

I'm trying to figure out the best way to recursively go through a [string]int map in Go. I'm building a game in which multiple countries are involved, and grouped together by teams of two in the end.

The goal is to match the first two countries with the lowest 'score' into its own group of two, and add it back to the collection giving the new map a total value of the scores of those countries.

Then recursively doing that to all the groups, ending up with one group and one total value in the end.

For example, if you had:

score := map[string]int{
        "Canada": 7,
        "US": 2,
        "Germany": 3,
        "Korea": 4,
}

group1 = {[US:2] [Germany:3]} with a total of 5

group1 would now be put back into the initial collection with a 'score' of 5 since it takes the two lowest scores. We would now have:

score := map[string]int{
        "Canada": 7,
        "Korea": 4,
        group1: `US:2 Germany:3` with a total of 5
}

If this was now the lowest score in the collection, the next iteration would be:

group2 = {[Korea:4] [group1:5]}

 score := map[string]int{
            "Canada": 7,
            group2: `Korea:4 group1:5` with a total of 9
  }

And so on until you're left with one.. I think the basic structure should be something like this. However, I'm unsure of the proper way to do this since the data structure is now encompassing a [string]int map, as well as this new map.

I realize this is not such a generic question, but could an interface be used for this? I'm very new to Go, so advice would be helpful.

Here is an example to further illustrate what I mean: https://play.golang.org/p/cnkTc0HBY4

  • 写回答

3条回答 默认 最新

  • duanlu9816 2017-08-30 18:37
    关注

    Your problem can "easy" be solved using a heap data structure.

    package main
    
    import (
        "container/heap"
        "fmt"
    )
    
    
    
    // Something that has a score
    type Scoreable interface {
        fmt.Stringer
        Score() int
    }
    
    
    
    // A country has a name and a score
    type Country struct {
        name  string
        score int
    }
    
    // Country implements Scoreable
    func (c Country) Score() int {
        return c.score
    }
    
    // ... and fmt.Stringer
    func (c Country) String() string {
        return fmt.Sprintf("%s [%d]", c.name, c.score)
    }
    
    
    
    // A team consists of two Scoreable's and has itself a score
    type Team struct {
        team1, team2 Scoreable
        score        int
    }
    
    // Team implements Scoreable
    func (t Team) Score() int {
        return t.score
    }
    
    // ... and fmt.Stringer
    func (t Team) String() string {
        return fmt.Sprintf("(%s + %s)", t.team1.String(), t.team2.String())
    }
    
    
    
    // The heap will be implemented using a slice of Scoreables
    type TeamHeap []Scoreable
    
    // TeamHeap implements heap.Interface
    func (th TeamHeap) Len() int {
        return len(th)
    }
    
    func (th TeamHeap) Less(i, j int) bool {
        return th[i].Score() < th[j].Score()
    }
    
    func (th TeamHeap) Swap(i, j int) {
        th[i], th[j] = th[j], th[i]
    }
    
    func (th *TeamHeap) Push(t interface{}) {
        *th = append(*th, t.(Scoreable))
    }
    
    func (th *TeamHeap) Pop() interface{} {
        old := *th
        n := len(old)
        t := old[n-1]
        *th = old[0 : n-1]
        return t
    }
    
    
    // The main function
    func main() {
    
        // Create a heap and initialize it
        teams := &TeamHeap{}
        heap.Init(teams)
    
        // Push the countries (NB: heap.Push(), not teams.Push())
        heap.Push(teams, Country{"Canada", 7})
        heap.Push(teams, Country{"US", 2})
        heap.Push(teams, Country{"Germany", 3})
        heap.Push(teams, Country{"Korea", 4})
    
        // Take the two teams with lowest score and make a new team of them
        // Repeat this until there's only one team left
        for teams.Len() > 1 {
            t1 := heap.Pop(teams).(Scoreable)
            t2 := heap.Pop(teams).(Scoreable)
            heap.Push(teams, Team{t1, t2, t1.Score() + t2.Score()})
        }
    
        // Print the teams that we now have in the heap
        for teams.Len() > 0 {
            t := heap.Pop(teams).(Team)
            fmt.Println(t)
        }
    }
    

    You can find runnable code on the Go Playground.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 kylin启动报错log4j类冲突
  • ¥15 超声波模块测距控制点灯,灯的闪烁很不稳定,经过调试发现测的距离偏大
  • ¥15 import arcpy出现importing _arcgisscripting 找不到相关程序
  • ¥15 onvif+openssl,vs2022编译openssl64
  • ¥15 iOS 自定义输入法-第三方输入法
  • ¥15 很想要一个很好的答案或提示
  • ¥15 扫描项目中发现AndroidOS.Agent、Android/SmsThief.LI!tr
  • ¥15 怀疑手机被监控,请问怎么解决和防止
  • ¥15 Qt下使用tcp获取数据的详细操作
  • ¥15 idea右下角设置编码是灰色的