将两个或多个 []map[string]interface{} 类型合并为一个在 Golang 中。

huangapple go评论88阅读模式
英文:

Merge two or more []map[string]interface{} types into one in Golang

问题

我正在使用Golang,由于某种原因,我需要合并来自不同数据库查询的结果,这些查询都会返回一个[]map[string]interface{}类型的结果。
我考虑使用Append,但是不太清楚是否可能实现这一点。
我最终得到的数据类型是什么?

显然,一个由字符串键的接口映射组成的数组应该能够简单地与另一个由字符串键的接口映射组成的数组"附加"(如果可以的话,就是连接)在一起!

那么,实现这个的机制是什么?

英文:

I'm using Golang and for some reason, I need to merge results from different database queries, all of which return me a []map[string]interface{}
I'm thinking of Append but its just not clear enough if this is even possible.
What is the final datatype I'm looking at?

Clearly, an array of maps of interfaces with keys as strings should be able to simply 'attach' (concat, if you may) to another array of maps of interfaces with keys as strings!

So what is the mechanism to achieve this?

答案1

得分: 20

即使答案已经在上面的评论中给出,我还是会发布一个简短的示例,展示如何实现这一点。

package main

import (
	"fmt"
)

func main() {
	result := []map[string]interface{}{}

	mp1 := map[string]interface{}{
		"one": 1,
		"two": 2,
	}

	mp2 := map[string]interface{}{
		"three": 3,
		"four":  4,
	}

	mp3 := make(map[string]interface{})
	for k, v := range mp1 {
		if _, ok := mp1[k]; ok {
			mp3[k] = v
		}
	}

	for k, v := range mp2 {
		if _, ok := mp2[k]; ok {
			mp3[k] = v
		}
	}

	result = append(result, mp1, mp2)
	fmt.Println(result)
}

输出结果为:

[map[one:1 two:2] map[three:3 four:4]]

Playground 示例

英文:

Even the answer is already given in the comments above i will post a short example how this can be achieved.

package main

import (
	"fmt"
)

func main() {
	result := []map[string]interface{}{}
	
	mp1 := map[string]interface{}{
		"one" : 1, 
		"two" : 2,
	}
	
	mp2 := map[string]interface{}{
		"three" : 3,
		"four" : 4,
	}
	
	mp3 := make(map[string]interface{})
	for k, v := range mp1 {
		if _, ok := mp1[k]; ok {
			mp3[k] = v			
		}
	}
	
	for k, v := range mp2 {
		if _, ok := mp2[k]; ok {
			mp3[k] = v
		}
	}

	result = append(result, mp1, mp2)
	fmt.Println(result)
}

The output will be:

[map[one:1 two:2] map[three:3 four:4]]

Playground example

答案2

得分: 13

另一个答案是正确的。你也可以编写一个辅助函数来避免重复的映射合并。

// 如果有需要,可以处理重复的键
func mergeMaps(maps ...map[string]interface{}) map[string]interface{} {
	result := make(map[string]interface{})
	for _, m := range maps {
		for k, v := range m {
			result[k] = v
		}
	}
	return result
}

func main() {
	log.Println(`started`)

	v := []map[string]interface{}{
		map[string]interface{}{
			`one`: 1,
			`two`: 2,
		},
		map[string]interface{}{
			`one`:   `I`,
			`three`: 3,
			`other`: `NAN`,
		},
		map[string]interface{}{
			`name`: `Bob`,
			`age`:  300,
		},
	}

	m := mergeMaps(v...)
	log.Println(m, len(m))
}

以上是代码的翻译。

英文:

The other answer is correct. You could also write a helper function to avoid repetitive map merges.

// overwriting duplicate keys, you should handle that if there is a need
func mergeMaps(maps ...map[string]interface{}) map[string]interface{} {
	result := make(map[string]interface{})
	for _, m := range maps {
		for k, v := range m {
			result[k] = v
		}
	}
	return result
}

func main() {
	log.Println(`started`)

	v := []map[string]interface{}{
		map[string]interface{}{
			`one`: 1,
			`two`: 2,
		},
		map[string]interface{}{
			`one`:   `I`,
			`three`: 3,
			`other`: `NAN`,
		},
		map[string]interface{}{
			`name`: `Bob`,
			`age`:  300,
		},
	}

	m := mergeMaps(v...)
	log.Println(m, len(m))
}

答案3

得分: 2

上述解决方案由EndreKaveh提出,两者都有效,但使用mergo更简单、方便和优化,适用于合并Go结构体和映射的广泛场景,除了合并map[string]interface{}。

package main

import (
    "fmt"
    "github.com/imdario/mergo"
)

func main() {
    mp1 := map[string]interface{}{
        "one" : 1, 
        "two" : 2,
    }

    mp2 := map[string]interface{}{
        "three" : 3,
        "four" : 4,
    }

    mergo.Merge(&mp1, mp2) //mergo.Merge(&dest,src)

    fmt.Println(mp1)
}

输出结果:

map[four:4 one:1 three:3 two:2]

P.S. - 在Golang中,没有保持顺序的概念。实际上,Go中的映射遍历总是以随机顺序进行的。因此,不要依赖映射的键的顺序。

英文:

The above solutions suggested by Endre and Kaveh both works, but it is much simpler, handy, and more optimized to use mergo when one wants to merge Go structs and maps which covers vast scenarios apart from merging map[string]interface{}

package main

import (
    "fmt"
    "github.com/imdario/mergo"
)

func main() {
    mp1 := map[string]interface{}{
        "one" : 1, 
        "two" : 2,
    }

    mp2 := map[string]interface{}{
        "three" : 3,
        "four" : 4,
    }

    mergo.Merge(&mp1, mp2) //mergo.Merge(&dest,src)
   
    fmt.Println(mp1)
}

Output:

map[four:4 one:1 three:3 two:2]

将两个或多个 []map[string]interface{} 类型合并为一个在 Golang 中。

P.S. - In Golang there is no order-preserving. Actually, iterating a map in Go is always in random order. So don't rely on a map's keys order.

huangapple
  • 本文由 发表于 2016年9月8日 20:50:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/39391437.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定