Copying all elements of a map into another
DictionaryGoCopyDictionary Problem Overview
Given
var dst, src map[K]V
I can copy all entries from src
into dst
by doing
for k, v := range src {
dst[k] = v
}
Is there a more idiomatic way to do this?
copy
only works on slices (and string
as a source).
Dictionary Solutions
Solution 1 - Dictionary
That looks like a perfectly fine way to do this to me. I don't think copying one map into another is common enough to have a one-liner solution.
Solution 2 - Dictionary
Using a simple for range
loop is the most efficient solution.
Note that a builtin copy
could not just copy the memory of src
to the address of dst
because they may have entirely different memory layout. Maps grow to accommodate the number of items stored in them. So for example if you have a map with a million elements, it occupies a lot more memory than a freshly created new map, and so a builtin copy
could not just copy memory without allocating new.
If your map is big, you can speed up copying elements if you may create the destination map having a big-enough capacity to avoid rehashing and reallocation (the initial capacity does not bound its size), e.g.:
dst := make(map[K]V, len(src))
for k, v := range src {
dst[k] = v
}
If performance is not an issue (e.g. you're working with small maps), a general solution may be created using the reflect
package:
func MapCopy(dst, src interface{}) {
dv, sv := reflect.ValueOf(dst), reflect.ValueOf(src)
for _, k := range sv.MapKeys() {
dv.SetMapIndex(k, sv.MapIndex(k))
}
}
This solution does not check if the arguments are really maps and if the destination is not nil
. Testing it:
m1 := map[int]string{1: "one", 2: "two"}
m2 := map[int]string{}
MapCopy(m2, m1)
fmt.Println(m2)
m3 := map[string]int{"one": 1, "two": 2}
m4 := map[string]int{}
MapCopy(m4, m3)
fmt.Println(m4)
Output (try it on the Go Playground):
map[1:one 2:two]
map[one:1 two:2]
Solution 3 - Dictionary
You could use github.com/linkosmos/mapop
input := map[string]interface{}{
"Key1": 2,
"key3": nil,
"val": 2,
"val2": "str",
"val3": 4,
}
input2 := map[string]interface{}{
"a2": "str",
"a3": 4,
}
input = mapop.Merge(input, input2)
input{"Key1": 2, "key3": nil, "val": 2, "val2": "str", "val3": 4, "a2": "str", "a3": 4}