2015-08-11 15 views
10

W R, próbuję utworzyć sposób przekształcania parametrów funkcji podanych w ... na wartości na uprzednio określonej liście w ramach funkcji zamykania.Użyj ..., aby zmodyfikować listę zagnieżdżoną w ramach funkcji

Chciałbym móc zrobić coś takiego:

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 będzie inna za każdym razem - jej obiektem ciało należy przesłać w żądaniu httr.

Mam funkcję, która działa, jeśli lista nie są zagnieżdżone list:

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" 

Ale nie mogę dowiedzieć się, jak go zmodyfikować tak, że działa z zagnieżdżonych list:

## 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" 

Co może być ? Domyślam się, że jakaś rekursja korzystająca z substitute.list mogła działać, ale nie mogłam niczego znaleźć, dlatego zwracam się do ciebie, internetu, o pomoc lub referencje, aby działało. Bardzo zobowiązany.

+2

czuje jak praca dla 'modyfikacji List (args_list, list (...)) ', ale nie całkiem podążam za twoim przykładowym przypadkiem – baptiste

+0

Hmm, modifyList() wygląda na dobrą odpowiedź, nie wiedział o tym. Przykładem jest podanie listy szablonów, której oczekuję od użytkownika, oraz podanie i błąd, jeśli nie zawierają właściwych wartości. – MarkeD

Odpowiedz

7

głębokość post-order pierwszy spacer z zagnieżdżonej listy

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

funkcję zastępczą, która zwraca zmodyfikowany listy zamiast mutacji w miejscu

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]]) 
} 

Przykład

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

Dzięki za odpowiedź! Jest to tak blisko, ale struktura wyjściowa nie jest taka sama jak oryginał. Czy można go zmodyfikować tak, aby str (t) wyglądał tak samo jak str (postwalk (function (x) replace.kv (x, s), t))? – MarkeD

+0

Naprawiono. Potrzebowałem tylko strażnika w 'replace.kv', ponieważ wymuszał on wszystko na liście. Alternatywą byłoby po prostu zwrócić 'x' zamiast' f (x) 'w funkcji' postwalk', ale jest bardziej ogólne, jak jest. Przepisuję również 'postwalk' przy użyciu' lapply', ale powinien działać jak poprzednio. –

+0

Dziękujemy! Ogólna funkcja była tym, czego szukałem, podoba mi się rekurencyjność. – MarkeD

Powiązane problemy