如何在 Go 中编写双向映射?

时间:2021-06-20 21:06:37

标签: go mapping

我正在编写一个简单的控制台游戏,并希望将玩家映射到一个符号。有两个玩家时,我的方法是这样的:

func playerToString(p player) string {
    if p == 0 {
        return "X"
    }
    return "O"
}

func stringToPlayer(s string) player {
    if s == "X" {
        return 0
    }
    return 1
}

当然,您也可以将其编写为两个映射,将 int 映射到 string,将 string 映射到 int。上述方法和地图方法似乎都容易出错。有没有更惯用的方式来写这个?也许一些非 iota 枚举方式?

3 个答案:

答案 0 :(得分:1)

[我假设您的示例只是最小的,并且您的实际映射有两个以上的选项。我还假设你的意思是双向映射]

我会写一张地图:

var player2string = map[int]string{
  0: "0",
  1: "X",
  // etc...
}

然后将创建一个函数来以编程方式填充不同的地图 string2player。像这样:

var player2string = map[int]string{
    0: "0",
    1: "X",
    // etc...
}

var string2player map[string]int = convertMap(player2string)

func convertMap(m map[int]string) map[string]int {
    inv := make(map[string]int)
    for k, v := range m {
        inv[v] = k
    }
    return inv

}

func main() {
    fmt.Println(player2string)
    fmt.Println(string2player)
}

Try it on the Go playground

答案 1 :(得分:1)

除了 Eli 的回答之外,您还可以进行另外两项更改。您可以使 to-symbol 函数成为 player 类型的方法。由于玩家值是整数(从零开始按顺序排列),您可以使用切片而不是映射来存储整数到符号的映射——存储和查找的效率更高一些。

type player int

var playerSymbols = []string{"X", "O", "A", "B", "C", "D", "E", "F", "G", "H"}

func (p player) Symbol() string {
    if int(p) < 0 || int(p) >= len(playerSymbols) {
        return "?" // or panic?
    }
    return playerSymbols[p]
}

这个方法签名甚至可以是 String() string,所以它是一个 fmt.Stringer,这对于打印内容和调试很有用。

答案 2 :(得分:0)

假设您不需要任何特定映射并且玩家整数值的序列为 0,1,2,3,...,25,您可以直接生成玩家符号而不使用地图,如下面的代码片段所示:-

type player int

func ToSymbol(p player) string {
    return fmt.Sprintf("%c", 'A' + p)
}

func ToPlayer(symbol string) player {
    return player([]rune(symbol)[0] - 'A')
}
相关问题