登录
首页 >  Golang >  Go问答

使用 Golang 递归展开地图

来源:stackoverflow

时间:2024-02-19 09:18:24 239浏览 收藏

在IT行业这个发展更新速度很快的行业,只有不停止的学习,才不会被行业所淘汰。如果你是Golang学习者,那么本文《使用 Golang 递归展开地图》就很适合你!本篇内容主要包括##content_title##,希望对大家的知识积累有所帮助,助力实战开发!

问题内容

使用下面的 json,我试图将其展平以方便访问。

示例有 2 个资源,此结构中可以有 n 个资源

"config": {
    "type": "r1",
    "properties": {
        "p1": "10",
        "p2": "10"
    },
    "connected": [
        {
            "type": "r3",
            "properties": {
              "p1": "10",
              "p2": "10"
            },
            "connected": [
                {}
        },
    ],
}

自定义扁平化逻辑

func keyvaluepairs(m interface{}) map[string]interface{} {
    kvs := make(map[string]interface{})
    if reflect.valueof(m).kind() == reflect.map {
        mp, ok := m.(map[string]interface{})
        if ok {
            var key string
            var value interface{}
            for k, v := range mp {
                switch k {
                case "type":
                    key = v.(string)
                case "properties":
                    value = v
                case "connected":
                    if collection, ok := v.([]interface{}); ok {
                        for _, c := range collection {
                            for nk, nv := range keyvaluepairs(c) {
                                nnv, _ := nv.(map[string]interface{})
                                _, ok := nnv["connectedto"]
                                if !ok {
                                   nnv["connectedto"] = key
                                }
                                kvs[nk] = nv
                            }
                        }
                    }
                default:
                    for nk, nv := range keyvaluepairs(v) {
                        kvs[nk] = nv
                    }
                }
            }
            if key != "" {
                kvs[key] = value
            }
        } else {
            for k, v := range m.(map[string]interface{}) {
                kvs[k] = v
            }
        }
    }
    return kvs
}

所需的输出有点波动,有些运行我得到了我需要的输出,有些执行“connectedto”属性为空。

{
"r1": {
        "p1": "10",
        "p2": "10"
    },
"r3" : {
        "connectedTo": "r1",
        "p1": "10",
        "p2": "10"
    },
}

我认为执行不是连续的。如果我错了,请纠正我。


正确答案


地图上的迭代顺序是随机的。详情见Why are iterations over maps random?How to iterate maps in insertion order?

现在看看你的循环:

var key string
var value interface{}
for k, v := range mp {
    switch k {
    case "type":
        key = v.(string)
    case "properties":
        value = v
    case "connected":
        if collection, ok := v.([]interface{}); ok {
            for _, c := range collection {
                for nk, nv := range keyvaluepairs(c) {
                    nnv, _ := nv.(map[string]interface{})
                    _, ok := nnv["connectedto"]
                    if !ok {
                       nnv["connectedto"] = key
                    }
                    kvs[nk] = nv
                }
            }
        }
    default:
        for nk, nv := range keyvaluepairs(v) {
            kvs[nk] = nv
        }
    }
}

您正在 "connected" 分支中使用 key 变量,但到达 "type""connected" 的顺序是不确定的(随机)。

"type" 分支是设置 key 的分支,但如果首先到达 "connected",则 key 将为空。

您不得依赖地图迭代顺序。

一个简单的解决方法是首先获取与 "type" 关联的值,并将其分配给 key (在 "connected" 分支中使用),循环之前。

例如:

key, _ := mp["type"].(string)
value := mp["properties"]
// Now process other properties:
for k, v := range mp {
    switch k {
    case "type", "properties": // Already handled
    case "connected":
        if collection, ok := v.([]interface{}); ok {
            for _, c := range collection {
                for nk, nv := range keyValuePairs(c) {
                    nnv, _ := nv.(map[string]interface{})
                    _, ok := nnv["connectedTo"]
                    if !ok {
                       nnv["connectedTo"] = key
                    }
                    kvs[nk] = nv
                }
            }
        }
    default:
        for nk, nv := range keyValuePairs(v) {
            kvs[nk] = nv
        }
    }
}

文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《使用 Golang 递归展开地图》文章吧,也可关注golang学习网公众号了解相关技术文章。

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>