2011-09-15 6 views

risposta

44

Sembra un modo perfetto per farlo. Non penso che copiare una mappa in un'altra sia abbastanza comune da avere una soluzione di un solo foglio.

+24

E 'un peccato 'copy' funziona solo su fette. –

+16

"Non penso che copiare una mappa in un'altra sia abbastanza comune" ... questo è il mio peggior problema principale. È qualcosa di veramente facile da fare su tipi nativi su ogni altra lingua là fuori. –

+7

@EduFelipe Sono d'accordo. La natura particolare dei tipi generici incorporati di Go (ad esempio mappe) e la mancanza di qualsiasi modo per ottenere lo stesso tipo di funzionalità in tipi definiti dall'utente (ad esempio, nessun supporto per i generici), è uno dei miei maggiori problemi con Go. Ed è solo uno dei tanti motivi per cui amo Rust. –

7

L'utilizzo di un ciclo semplice for range è la soluzione più efficiente.

Si noti che un copy integrato non può semplicemente copiare la memoria di src all'indirizzo dst perché potrebbe avere un layout di memoria completamente diverso. Le mappe crescono per contenere il numero di elementi memorizzati in esse. Ad esempio, se si dispone di una mappa con un milione di elementi, occupa molta più memoria rispetto a una nuova mappa appena creata e quindi un copy integrato non può semplicemente copiare la memoria senza allocare nuovo.

Se la mappa è grande, è possibile accelerare la copia di elementi se si può creare la mappa destinazione fornito di una grande capacità sufficiente per evitare rimasticare e riallocazione (la capacità iniziale non legato le sue dimensioni), ad esempio:

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

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

Se le prestazioni non è un problema (ad esempio, si sta lavorando con una piccola mappe), una soluzione generale può essere creato utilizzando il pacchetto 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)) 
    } 
} 

Questa soluzione non controlla se gli argomenti sono davvero mappe e se la destinazione non lo è nil. Testarlo:

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) 

uscita (provate sul Go Playground):

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

Si potrebbe utilizzare 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} 
Problemi correlati