Python 喜欢 GO Lang 中的嵌套字典

Python like nested dictionary in GO Lang

免责声明:我最近开始学习围棋。所以如果你们觉得这个问题很幼稚,请见谅。

我基本上是在尝试使用地图在 Go 中复制类似 Python 的嵌套字典行为。

这是一个简单的 python 函数,我想将其转换为 Go

def generate_chart():

    outcome_chart = {}

    A_LIST = ['a1', 'a2', 'a3', 'a4', ....., 'a10']
    B_LIST = ['b1', 'b2', 'b3', 'b4', ....., 'b10']
    C_LIST = ['c1', 'c2', 'c3', 'c4', ....., 'c10']

    for a in A_LIST:
        for b in B_LIST:
            for c in C_LIST:
                outcome_chart[a] = outcome_chart.get(a) or {}
                outcome_chart[a][b] = outcome_chart[a].get(b) or {}
                result = "some string from external source, would be different on each request" 
                outcome_chart[a][b].update({c: result})

    return outcome_chart

想法很简单,我有 3 个字符串列表。并尝试为不同的组合创建 map/chart。 此函数后的示例 运行

{
   'a1': {'b1': {'c1': 'somestring'}},
   ...
   'a2': {'b1': {'c3': 'someotherstring'}},
   ...
   'a6': {'b7': {'c2': 'string'}},
   ...
 }

现在基于我对 Go 的了解,我已经想出了这段代码,但它并不完整,因为我卡在了中间。

func generateChart() map[string]map[string]map[string]string {
    var result string
    var outcome_chart = map[string]map[string]map[string]string{}
    for _, a := range A_LIST {
        for _, b := range B_LIST {
            for _, c := range C_LIST {
                
                result = "some string from external source, would be different on each request" 

                if _, ok := outcome_chart[a]; ok {
                    if _, found := outcome_chart[a][b]; found {
                        if _, in := outcome_chart[a][b][c]; in {
                            outcome_chart[a][b][c] = result
                        } else {
                            outcome_chart[a][b] = map[string]string{c: result}
                        }
                    } else {
                        outcome_chart[a] = map[string]map[string]string{b: {c: result}}
                    }
                    outcome_chart[a] = # got stuck here, dont know if the previous lines are also correct.
                }
            }
        }
    }

    return outcome_chart

我可能以一种完全错误的方式来做这件事。可能有一个使用 struct or/and interface 的解决方案,但正如我提到的,我仍在尝试将自己暴露在 GO 世界中。所以欢迎大家feedback/suggestions/inputs。

PS:这只是 3 级嵌套,因此手动编写 3 级地图仍然是可扩展的,但是我们如何才能实现类似的嵌套级别,比如 100 或 1000 甚至无限。

Go 中的等价物:

func generateChart() map[string]map[string]map[string]string {
    var outcome_chart = map[string]map[string]map[string]string{}
    for _, a := range A_LIST {
        for _, b := range B_LIST {
            for _, c := range C_LIST {
                if _, ok := outcome_chart[a]; !ok {
                    outcome_chart[a] = map[string]map[string]string{}
                }

                if _, ok := outcome_chart[a][b]; !ok {
                    outcome_chart[a][b] = map[string]string{}
                }

                result := "some string from external source, would be different on each request"
                outcome_chart[a][b][c] = result
            }
        }
    }
    return outcome_chart
}

实现相同目标的更经济的方法:

func generateChart() map[string]map[string]map[string]string {
    var outcome_chart = map[string]map[string]map[string]string{}
    for _, a := range A_LIST {
        if _, ok := outcome_chart[a]; !ok {
            outcome_chart[a] = map[string]map[string]string{}
        }

        for _, b := range B_LIST {
            if _, ok := outcome_chart[a][b]; !ok {
                outcome_chart[a][b] = map[string]string{}
            }

            for _, c := range C_LIST {
                result := "some string from external source, would be different on each request"
                outcome_chart[a][b][c] = result
            }
        }
    }

    return outcome_chart
}

对于更嵌套的内容,为了方便起见,您可以使用声明的递归类型和一些方法:

type Chart struct {
    M map[string]*Chart
    V string
}

func newChart() *Chart {
    return &Chart{M: make(map[string]*Chart)}
}

func (c *Chart) addIfEmpty(key string) *Chart {
    if _, ok := c.M[key]; !ok {
        c.M[key] = newChart()
    }
    return c.M[key]
}

func generateChart() *Chart {
    var chart = newChart()
    for _, a := range A_LIST {
        aChart := chart.addIfEmpty(a)
        for _, b := range B_LIST {
            bChart := aChart.addIfEmpty(b)
            for _, c := range C_LIST {
                result := "some string from external source, would be different on each request"
                bChart.addIfEmpty(c).V = result
            }
        }
    }
    return chart
}