Copying all elements of a map into another

DictionaryGoCopy

Dictionary 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}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMike SamuelView Question on Stackoverflow
Solution 1 - DictionaryLily BallardView Answer on Stackoverflow
Solution 2 - DictionaryiczaView Answer on Stackoverflow
Solution 3 - DictionaryErnestas PoskusView Answer on Stackoverflow