2015-08-11 26 views
10

In R versuche ich, eine Möglichkeit zu schaffen, Funktionsparameter in ... zu Werten in einer vorgegebenen Liste innerhalb einer Closure-Funktion übergeben zu transformieren.Verwenden Sie ... zum Ändern einer verschachtelten Liste innerhalb einer Funktion

Ich möchte in der Lage sein, so etwas zu tun:

function_generator <- function(args_list = list(a = "a", 
               b = "b", 
               c = list(d = "d", 
                 e = "e")){ 

    g <- function(...){ 
     ## ... will have same names as args list 
     ## e.g. a = "changed_a", d = "changed_d" 
     ## if absent, then args_list stays the same e.g. b="b", e="e" 
     arguments <- list(...) 
     modified_args_list <- amazing_function(arguments, args_list) 
     return(modified_args_list) 
     } 

    } 

args_list jedes Mal anders sein wird - es ist ein Körper-Objekt in einem httr Anfrage gesendet werden.

Ich habe eine Funktion habe, dass, wenn die Liste funktioniert nicht Listen verschachtelt ist:

substitute.list <- function(template, replace_me){ 

    template[names(replace_me)] <- 
    replace_me[intersect(names(template),names(replace_me))] 

    return(template) 

} 

t <- list(a = "a", b="b", c="c") 
s <- list(a = "changed_a", c = "changed_c") 

substitute.list(t, s) 
> $a 
>[1] "changed_a" 

>$b 
>[1] "b" 

>$c 
>[1] "changed_c" 

Aber ich kann nicht herausfinden, wie es zu ändern, so dass es mit verschachtelten Listen funktioniert:

## desired output 
t <- list(a = "a", b = "b", c = list(d = "d", e = "e")) 
s <- list(a = "changed_a", d = "changed_d") 

str(t) 
List of 3 
$ a: chr "a1" 
$ b: chr "b1" 
$ c:List of 2 
    ..$ d: chr "d1" 
    ..$ e: chr "e1" 

amaze <- amazing_function(t, s) 

str(amaze) 
List of 3 
$ a: chr "changed_a" 
$ b: chr "b1" 
$ c:List of 2 
    ..$ d: chr "changed_d" 
    ..$ e: chr "e1" 

Was könnte amazing_function sein? Ich denke, eine Art von Rekursion mit substitute.list könnte funktionieren, aber nicht in der Lage gewesen, etwas zu finden, daher wende ich mich an Sie, Internet, um Hilfe oder Referenzen, damit es funktioniert. Viel verpflichtet.

+2

es sich anfühlt wie ein Job für 'modifizieren Liste (args_list, list (...)) ', aber ich folge nicht ganz Ihrem Beispielfall – baptiste

+0

Hmm, modifyList() sieht gut aus, war mir dessen nicht bewusst. Das Beispiel ist, ich möchte eine Vorlagenliste bereitstellen, die der Benutzer erwartet, und werfen und Fehler, wenn sie nicht die richtigen Werte eingeben. – MarkeD

Antwort

7

Post-Ordnung Tiefe gehen zuerst von verschachtelten Liste

postwalk<-function(x,f) { 
    if(is.list(x)) f(lapply(x,postwalk,f)) else f(x) 
} 

Ersatzfunktion, die eher Liste geändert Renditen als an Ort und Stelle mutiert

replace.kv<-function(x,m) { 
    if(!is.list(x)) return(x) 
    i<-match(names(x),names(m)); 
    w<-which(!is.na(i)); 
    replace(x,w,m[i[w]]) 
} 

Beispiel

t<-list(a="a1", b="b1", c=list(d="d1", e="e1")) 
s<-list(a="a2", d="d2") 

str(postwalk(t,function(x) replace.kv(x,s))) 
 
List of 3 
$ a: chr "a2" 
$ b: chr "b1" 
$ c:List of 2 
    ..$ d: chr "d2" 
    ..$ e: chr "e1" 
+0

Danke für die Antwort! Dies ist so nah, aber die Ausgabestruktur ist nicht gleich wie das Original. Ist es möglich, es so zu modifizieren, dass str (t) genauso aussieht wie str (postwalk (funktion (x) ersetzen.kv (x, s), t))? – MarkeD

+0

Behoben. Ich brauchte nur einen Wächter in 'replace.kv', da es alles auf eine Liste zwang. Eine Alternative wäre, einfach "x" anstelle von "f (x)" in der "postwalk" -Funktion zurückzugeben, aber es ist allgemeiner wie es ist. Ich habe auch 'postwalk' mit 'lapply' umgeschrieben, aber es sollte wie vorher funktionieren. –

+0

Danke! Eine allgemeine Funktion war, was ich suchte, ich mag die Rekursivität des Postwalks. – MarkeD

Verwandte Themen