2011-09-15 9 views

Odpowiedz

44

To wygląda na doskonały sposób, aby mi to zrobić. Nie sądzę, że kopiowanie jednej mapy do drugiej jest dość powszechne, aby mieć rozwiązanie oparte na jednej linijce.

+24

Szkoda 'copy' działa tylko na plasterki. –

+16

"Nie sądzę, żeby kopiowanie jednej mapy do drugiej było dość powszechne" ... to jest mój główny zwierzak, który się nie przejmuje. To jest naprawdę łatwe do zrobienia w natywnych typach w każdym innym języku. –

+7

@EduFelipe Zgadzam się. Szczególny charakter wbudowanych typów generycznych Go (np. Map) i brak jakiegokolwiek sposobu na uzyskanie tego samego rodzaju funkcjonalności w typach zdefiniowanych przez użytkownika (np. Brak obsługi generycznych) jest jednym z moich największych problemów z Go. I to tylko jeden z wielu powodów, dla których kocham Rusta. –

7

Korzystanie z prostej pętli for range jest najbardziej wydajnym rozwiązaniem.

Należy pamiętać, że wbudowany copy nie może po prostu skopiować pamięci src na adres dst, ponieważ mogą one mieć zupełnie inny układ pamięci. Mapy rosną, aby pomieścić liczbę przechowywanych w nich przedmiotów. Na przykład, jeśli masz mapę z milionem elementów, zajmuje ona o wiele więcej pamięci niż świeżo utworzona nowa mapa, więc wbudowany copy nie może po prostu skopiować pamięci bez przydzielania nowych.

Jeśli mapa jest duża, można przyspieszyć kopiowanie elementów, jeśli można utworzyć mapę docelowy mający duży-wystarczająco zdolność do unikania hashuje i realokacja (początkowa pojemność nie wiąże jej rozmiar), np:

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

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

Jeżeli wydajność nie jest problemem (np pracujesz z małych mapach), ogólne rozwiązanie mogą być tworzone za pomocą pakietu 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)) 
    } 
} 

to rozwiązanie nie sprawdza, czy argumenty są naprawdę mapy a jeśli miejsce docelowe nie jest nil. Testowanie go:

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 (spróbuj go na Go Playground):

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

Można użyć 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} 
Powiązane problemy