Mam funkcję rekurencyjną, która tworzy obiekty reprezentujące ścieżki plików (klucze to ścieżki, a wartości to informacje o pliku). Jest rekurencyjna, ponieważ jest przeznaczona tylko do obsługi plików, więc jeśli napotkany zostanie katalog, funkcja jest rekurencyjnie wywoływana w katalogu.
Biorąc to wszystko pod uwagę, chciałbym zrobić odpowiednik set union na dwóch mapach (tj. Mapa „główna” zaktualizowana wartościami z wywołania rekurencyjnego). Czy istnieje idiomatyczny sposób na zrobienie tego poza iteracją po jednej mapie i przypisaniem każdemu kluczowi, wartości w nim tej samej rzeczy na drugiej mapie?
Czyli: podane a,b
są typu map [string] *SomeObject
, a a
i b
są ostatecznie zaludnionych, czy jest jakiś sposób na aktualizację a
ze wszystkimi wartościami b
?
Odpowiedzi:
W standardowych pakietach nie ma wbudowanego sposobu ani żadnej metody na wykonanie takiego scalenia.
Idomatycznym sposobem jest po prostu iteracja:
for k, v := range b { a[k] = v }
źródło
a[k] = v
naa[k] = a[k] + v
lub coś takiego.a[k] = append(a[k], v...)
Jeśli masz kilka zagnieżdżonych map
left
iright
, ta funkcja będzie rekurencyjnie dodawać elementy zright
doleft
. Jeśli klucz jest już wleft
środku, sięgamy głębiej do struktury i próbujemy tylko dodawać kluczeleft
(np. Nigdy ich nie zastępować).type m = map[string]interface{} // Given two maps, recursively merge right into left, NEVER replacing any key that already exists in left func mergeKeys(left, right m) m { for key, rightVal := range right { if leftVal, present := left[key]; present { //then we don't want to replace it - recurse left[key] = mergeKeys(leftVal.(m), rightVal.(m)) } else { // key not in left so we can just shove it in left[key] = rightVal } } return left }
UWAGA: nie zajmuję się przypadkiem, w którym sama wartość nie jest a
map[string]interface{}
. Więc jeśli masz,left["x"] = 1
aright["x"] = 2
powyższy kod będzie panikować podczas próbyleftVal.(m)
.źródło