Disclaimer: I recently started learning Go. so if this question seems to you guys very naive, please pardon me.
I'm basically trying to replicate the Python-like nested dictionary behaviour in Go using the map.
here is a simple python function that I want to convert to 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
the idea is simple, I have 3 lists of strings. and trying to create a map/chart for different combinations. An example after this function run
{
'a1': {'b1': {'c1': 'somestring'}},
...
'a2': {'b1': {'c3': 'someotherstring'}},
...
'a6': {'b7': {'c2': 'string'}},
...
}
Now based on my very little knowledge of Go, I've come up with this piece of code but it's not complete as i got stuck in the middle.
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
I might be doing it in a completely wrong way. There might be a solution using struct or/and interface but as I mentioned I'm still trying to expose myself to GO world. So all the feedback/suggestions/inputs are welcome.
PS: this was only 3 level nested so it was still scalable to write manually 3 level map but how can we achieve similar thing for more nesting level lets say 100s or 1000s or even infinite.
CodePudding user response:
The equivalent in 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
}
A more economical approach to achieve the same:
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
}
For something more nested you can use a declared recursive type sprinkled with some methods for convenience:
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
}