英文:
How to efficiently custom flatten a map
问题
根据传递的resourcesToCreate参数,我必须相应地创建它们以创建流程。
但现在的问题是,在分配funcInput时,json实际上是根据创建的流程嵌套的,属性可以出现在任何位置,所以我不能硬编码。
例如:
"config": {
"type": "func1",
"config": {
"param1": "10",
"param2": "10"
},
"connected": [
{
"type": "func3",
"config": {
"param1": "10",
"param2": "10"
},
"connected": [
{}
},
],
}
所以我想,如果我将其展平,我可以不考虑流程而引用它:
{
"func1": {
"param1": "10",
"param2": "10"
},
"func3" : {
"param1": "10",
"param2": "10"
},
}
目前的代码将json展平,但在获取所需输出时遇到了问题:
func Flatten(prefix string, src map[string]interface{}, dest map[string]interface{}) {
if len(prefix) > 0 {
prefix += "."
}
for k, v := range src {
switch child := v.(type) {
case map[string]interface{}:
Flatten2(prefix+k, child, dest)
case []interface{}:
for i := 0; i < len(child); i++ {
dest[prefix+k+"."+strconv.Itoa(i)] = child[i]
}
default:
dest[prefix+k] = v
}
}
}
英文:
So based on the resourcesToCreate parameter passed I have to create them accordingly to create the flow
But now the problem is while assigning the funcInput the json is actually nested based on the flow it creates and attributes can be present anywhere so I cant harcode.
Example
"config": {
"type": "func1",
"config": {
"param1": "10",
"param2": "10"
},
"connected": [
{
"type": "func3",
"config": {
"param1": "10",
"param2": "10"
},
"connected": [
{}
},
],
}
So was thinking it I flatten it like this I can refer irrespective of the flow
{
"func1": {
"param1": "10",
"param2": "10"
},
"func3" : {
"param1": "10",
"param2": "10"
},
}
So the code currently fattens the json but having trouble getting the desired output
func Flatten(prefix string, src map[string]interface{}, dest map[string]interface{}) {
if len(prefix) > 0 {
prefix += "."
}
for k, v := range src {
switch child := v.(type) {
case map[string]interface{}:
Flatten2(prefix+k, child, dest)
case []interface{}:
for i := 0; i < len(child); i++ {
dest[prefix+k+"."+strconv.Itoa(i)] = child[i]
}
default:
dest[prefix+k] = v
}
}
}
``
</details>
# 答案1
**得分**: 1
这个扁平化操作更像是提取值。通用的方法不可能存在,只能依赖于JSON的键,比如`type`、`properties`和`connected`,来高效地提取`func`和`param`的值。你的扁平化函数应该像这样:
```go
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) {
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
}
相同的代码示例输入:Go Playground
为了更好地理解代码片段,请查看这个gist,在那里我实际上是将一个JSON扁平化为最后的键值对。
英文:
This flattening is more like extracting values. Generic way is not possible but to depend on the JSON keys like type
, properties
and connected
to efficiently extract the func
and param
values. Your flatten function should be like:
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) {
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
}
The same code with example inputs: Go Playground
For better understanding the code snippet, check this gist where I was actually flattening a JSON to very last key-value pairs.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论