Ich denke, dass Sie hier Ihre eigene rekursive Funktion schreiben müssen.
Eine Funktion, die zwei Listen akzeptiert, list1
und list2
. If:
list1[[name]]
existiert, aber nicht list2[[name]]
, verwenden list1[[name]]
;
list1[[name]]
existiert ebenso wie list2[[name]]
und beide sind keine Listen, verwenden Sie list2[[name]]
;
- andernfalls mit
list1[[name]]
und list2[[name]]
als die neuen Listen rekursiv.
Etwas wie:
myMerge <- function (list1, list2) {
allNames <- unique(c(names(list1), names(list2)))
merged <- list1 # we will copy over/replace values from list2 as necessary
for (x in allNames) {
# convenience
a <- list1[[x]]
b <- list2[[x]]
if (is.null(a)) {
# only exists in list2, copy over
merged[[x]] <- b
} else if (is.list(a) && is.list(b)) {
# recurse
merged[[x]] <- myMerge(a, b)
} else if (!is.null(b)) {
# replace the list1 value with the list2 value (if it exists)
merged[[x]] <- b
}
}
return(merged)
}
Caveats - wenn Ihre Listen sind seltsam zusammengeführt werden, könnten Sie seltsame Ausgabe erhalten. Zum Beispiel:
a <- list(a=list(a=1, b=2), b=3)
b <- list(a=2)
dann Ihre fusionierte Liste a=2, b=3
. Dies liegt daran, dass der Wert b$a
den Wert von a$a
überschreibt, auch wenn a$a
eine Liste ist (Sie haben nicht angegeben, was passieren würde, wenn dies der Fall wäre). Es ist jedoch einfach genug, myMerge
zu modifizieren, um diese Art von Fällen zu behandeln. Erinnern Sie sich einfach - benutzen Sie is.list
, um zu testen, ob es eine Liste ist, und is.null(myList$a)
, um zu sehen, ob der Eintrag a
in der Liste myList
existiert.
Hier ist die "vektorisiert" Version sapply
mit:
merge.lists <- function(a, b) {
a.names <- names(a)
b.names <- names(b)
m.names <- sort(unique(c(a.names, b.names)))
sapply(m.names, function(i) {
if (is.list(a[[i]]) & is.list(b[[i]])) merge.lists(a[[i]], b[[i]])
else if (i %in% b.names) b[[i]]
else a[[i]]
}, simplify = FALSE)
}
gibt Ich bin nicht sicher, ob diese vektorisiert werden kann mit 'vapply'/ähnlich, während immer noch die verschachtelte Struktur zu halten. –
Das ist großartig! Genau das, was ich brauche. BTW, mein Beispiel hatte den "seltsamen" Listeneintrag ("d" in beiden Listen). – zeeMonkeez
Wenn Sie 'if (! Is.null (a) &&! Is.null (b) &&xor (is.list (a), is.list (b))) { fusioniert [[x]] <- c (a, b) } ' am Anfang dieser if-Anweisung können Sie diesen Kantenfall berücksichtigen, wobei das Überschreiben freilich verloren geht. –