Ich versuche, den Inhalt einer map ( amap
) in eine andere ( aSuperMap
) zu kopieren und dann zu löschen, amap
damit sie bei der nächsten Iteration / Schleife neue Werte annehmen kann. Das Problem ist, dass Sie die Karte nicht löschen können, ohne ihre Referenz auch in der Supermap zu löschen . Hier ist ein Pseudocode.
for something := range fruits{
aMap := make(map[string]aStruct)
aSuperMap := make(map[string]map[string]aStruct)
for x := range something{
aMap[x] = aData
aSuperMap[y] = aMap
delete(aMap, x)
}
//save aSuperMap
saveASuperMap(something)
}
Ich habe auch einige dynamische Sachen ausprobiert, aber offensichtlich gibt es einen Fehler (kann nicht auf Null zugewiesen werden)
aSuperMap[y][x] = aData
Die Frage ist, wie ich eine assoziative Karte erstellen kann. In PHP verwende ich einfach aSuperMap [y] [x] = aData. Es scheint, dass Golang keine offensichtliche Methode hat. Wenn ich delete(aMap, x)
seinen Verweis aus der Superkarte lösche, wird er ebenfalls gelöscht. Wenn ich es nicht lösche, erhält die Supermap doppelte Daten. Grundsätzlich erhält es in jeder Schleife aMap
den neuen Wert plus alle alten Werte.
Ich würde Rekursion nur für den Fall verwenden, damit Sie das tief kopieren
map
und böse Überraschungen vermeiden können, falls Sie einmap
Element ändern sollten , dasmap
selbst ist.Hier ist ein Beispiel in einer utils.go :
package utils func CopyMap(m map[string]interface{}) map[string]interface{} { cp := make(map[string]interface{}) for k, v := range m { vm, ok := v.(map[string]interface{}) if ok { cp[k] = CopyMap(vm) } else { cp[k] = v } } return cp }
Und seine Testdatei (dh utils_test.go ):
package utils import ( "testing" "github.com/stretchr/testify/require" ) func TestCopyMap(t *testing.T) { m1 := map[string]interface{}{ "a": "bbb", "b": map[string]interface{}{ "c": 123, }, } m2 := CopyMap(m1) m1["a"] = "zzz" delete(m1, "b") require.Equal(t, map[string]interface{}{"a": "zzz"}, m1) require.Equal(t, map[string]interface{}{ "a": "bbb", "b": map[string]interface{}{ "c": 123, }, }, m2) }
Die Anpassung sollte einfach genug sein, wenn der
map
Schlüssel etwas anderes als a sein sollstring
.quelle
Sie müssen jedes Schlüssel / Wert-Paar manuell in ein neues kopieren
map
. Dies ist eine Schleife, die Benutzer jedes Mal neu programmieren müssen, wenn sie eine tiefe Kopie von a wünschenmap
.Sie können die Funktion hierfür automatisch generieren, indem Sie mit
mapper
aus demmaps
Paket installierenund läuft
mapper -types string:aStruct
die generiert die Datei
map_float_astruct.go
enthält nicht nur eine (tief)Copy
für die Karte , sondern auch andere „fehlenden“map
FunktionenContainsKey
,ContainsValue
,GetKeys
undGetValues
:func ContainsKeyStringAStruct(m map[string]aStruct, k string) bool { _, ok := m[k] return ok } func ContainsValueStringAStruct(m map[string]aStruct, v aStruct) bool { for _, mValue := range m { if mValue == v { return true } } return false } func GetKeysStringAStruct(m map[string]aStruct) []string { keys := []string{} for k, _ := range m { keys = append(keys, k) } return keys } func GetValuesStringAStruct(m map[string]aStruct) []aStruct { values := []aStruct{} for _, v := range m { values = append(values, v) } return values } func CopyStringAStruct(m map[string]aStruct) map[string]aStruct { copyMap := map[string]aStruct{} for k, v := range m { copyMap[k] = v } return copyMap }
Vollständige Offenlegung: Ich bin der Schöpfer dieses Tools. Ich habe es und das darin enthaltene Paket erstellt, weil ich diese Algorithmen für Go
map
für verschiedene Typkombinationen ständig neu geschrieben habe .quelle
Einzelelementkopie, es scheint für mich nur mit einem einfachen Beispiel zu funktionieren.
maps := map[string]int { "alice":12, "jimmy":15, } maps2 := make(map[string]int) for k2,v2 := range maps { maps2[k2] = v2 } maps2["miki"]=rand.Intn(100) fmt.Println("maps: ",maps," vs. ","maps2: ",maps2)
quelle
Wie in seongs Kommentar angegeben :
Keine der hier aufgeführten Lösungen scheint jedoch eine Lösung für eine ordnungsgemäße Tiefenkopie zu bieten, die auch Slices abdeckt.
Ich habe die Antwort von Francesco Casula leicht geändert , um sowohl Karten als auch Slices zu berücksichtigen.
Dies sollte sowohl das Kopieren Ihrer Karte selbst als auch das Kopieren von untergeordneten Karten oder Slices umfassen. Beide sind von demselben Problem der "zugrunde liegenden Datenstruktur" betroffen. Es enthält auch eine Dienstprogrammfunktion zum direkten Ausführen derselben Art von Deep Copy für ein Slice.
Beachten Sie, dass die Scheiben in der resultierenden Karte vom Typ sein
[]interface{}
, so dass , wenn sie verwenden, müssen Sie verwenden Typ Behauptung den Wert in der erwarteten Art abzurufen.Beispiel Verwendung
copy := CopyableMap(originalMap).DeepCopy()
Quelldatei (
util.go
)package utils type CopyableMap map[string]interface{} type CopyableSlice []interface{} // DeepCopy will create a deep copy of this map. The depth of this // copy is all inclusive. Both maps and slices will be considered when // making the copy. func (m CopyableMap) DeepCopy() map[string]interface{} { result := map[string]interface{}{} for k,v := range m { // Handle maps mapvalue,isMap := v.(map[string]interface{}) if isMap { result[k] = CopyableMap(mapvalue).DeepCopy() continue } // Handle slices slicevalue,isSlice := v.([]interface{}) if isSlice { result[k] = CopyableSlice(slicevalue).DeepCopy() continue } result[k] = v } return result } // DeepCopy will create a deep copy of this slice. The depth of this // copy is all inclusive. Both maps and slices will be considered when // making the copy. func (s CopyableSlice) DeepCopy() []interface{} { result := []interface{}{} for _,v := range s { // Handle maps mapvalue,isMap := v.(map[string]interface{}) if isMap { result = append(result, CopyableMap(mapvalue).DeepCopy()) continue } // Handle slices slicevalue,isSlice := v.([]interface{}) if isSlice { result = append(result, CopyableSlice(slicevalue).DeepCopy()) continue } result = append(result, v) } return result }
Testdatei (
util_tests.go
)package utils import ( "testing" "github.com/stretchr/testify/require" ) func TestCopyMap(t *testing.T) { m1 := map[string]interface{}{ "a": "bbb", "b": map[string]interface{}{ "c": 123, }, "c": []interface{} { "d", "e", map[string]interface{} { "f": "g", }, }, } m2 := CopyableMap(m1).DeepCopy() m1["a"] = "zzz" delete(m1, "b") m1["c"].([]interface{})[1] = "x" m1["c"].([]interface{})[2].(map[string]interface{})["f"] = "h" require.Equal(t, map[string]interface{}{ "a": "zzz", "c": []interface{} { "d", "x", map[string]interface{} { "f": "h", }, }, }, m1) require.Equal(t, map[string]interface{}{ "a": "bbb", "b": map[string]interface{}{ "c": 123, }, "c": []interface{} { "d", "e", map[string]interface{} { "f": "g", }, }, }, m2) }
quelle