2011-09-15 5 views
59

에지도의 모든 요소를 ​​복사을 감안할 때 다른

var dst, src map[K]V 

내가이 일을 더 관용적 방법이 있나요

for k, v := range src { 
    dst[k] = v 
} 

을 수행하여 dstsrc에서 모든 항목을 복사 할 수 있습니다?

copy은 슬라이스에서만 작동하며 소스로는 string입니다.

답변

44

나에게이 작업을 수행 할 수있는 완벽한 방법입니다. 한 맵을 다른 맵으로 복사하는 것이 일회용 솔루션을 사용하기에 충분할만큼 일반적이라고 생각하지 않습니다.

+24

사용할 수있는'copy'는 조각에서 작동합니다. –

+16

"한지도를 다른지도로 복사하는 것이 일반적으로 충분하지 않다고 생각합니다."... 그것은 내 주인공입니다. 이것은 다른 모든 언어에서 네이티브 타입을 사용하기가 정말 쉽습니다. –

+7

@EduFelipe 동의합니다. Go의 빌트인 제네릭 유형 (예 :지도)의 특수한 특성과 사용자 정의 유형 (예 : 제네릭에 대한 지원 없음)에서 같은 종류의 기능을 사용하지 못하는 것이 Go의 가장 큰 문제 중 하나입니다. 그리고 그것은 녹을 좋아하는 많은 이유 중 하나 일뿐입니다. –

7

간단한 for range 루프를 사용하는 것이 가장 효율적인 솔루션입니다.

copy은 의 메모리가 완전히 다른 메모리 레이아웃을 가질 수 있으므로 dst의 주소로 복사 할 수 없습니다. 지도는 저장된 항목의 수를 수용 할 수 있도록 확장됩니다. 따라서 예를 들어 백만 개의 요소가있는지도가 있으면 새로 만든지도보다 훨씬 많은 메모리를 차지하므로 내장 된 copy은 새지도를 할당하지 않고 메모리를 복사 할 수 없습니다.

:

지도가 큰 경우, 당신은 당신이 다시 해싱 및 재 할당 피하기 위해 큰 충분한 용량을 갖는 대상지도를 만들 수 있습니다 경우 요소를 복사 속도를 높일 수는, 예를 들어, (초기 용량은 크기를 구속하지 않습니다)

dst := make(map[K]V, len(src)) 

for k, v := range src { 
    dst[k] = v 
} 

성능 (예를 들어, 당신이 작은지도로 작업) 문제, 일반적인 솔루션은 reflect 패키지를 사용하여 생성 할 수없는 경우 : 인수가 정말 매핑하는 경우

func MapCopy(dst, src interface{}) { 
    dv, sv := reflect.ValueOf(dst), reflect.ValueOf(src) 

    for _, k := range sv.MapKeys() { 
     dv.SetMapIndex(k, sv.MapIndex(k)) 
    } 
} 

이 솔루션은 확인하지 않습니다는 목적지가 아닌 경우 nil. 그것을 테스트 :

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) 

출력합니다 (Go Playground에 그것을 시도) :

map[1:one 2:two] 
map[one:1 two:2] 
2

당신은 그것은 부끄러운 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}