2015-08-11 20 views
10

In R, sto tentando di creare un modo per trasformare i parametri di funzione forniti in ... in valori in un elenco predeterminato all'interno di una funzione di chiusura.Utilizzare ... per modificare un elenco annidato all'interno di una funzione

mi piacerebbe essere in grado di fare qualcosa del genere:

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 sarà diverso ogni volta - è un oggetto corpo da inviare in una richiesta httr.

Ho una funzione che funziona se l'elenco non hanno nidificato liste:

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" 

Ma non riesco a capire come modificarlo in modo che funzioni con le liste nidificate:

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

Che cosa potrebbe essere amazing_function? Immagino che una sorta di ricorsione usando substitute.list potrebbe funzionare, ma non sono stato in grado di trovare nulla, quindi mi rivolgo a te, internet, aiuto o riferimenti per farlo funzionare. Molto obbligato.

+2

ci si sente come un lavoro per 'modificare List (args_list, list (...)) ', ma non seguo il tuo esempio di esempio – baptiste

+0

Hmm, modifyList() sembra una buona risposta, non ne era a conoscenza. L'esempio è che voglio fornire un elenco di template che mi aspetto che l'utente fornisca, e che lanci ed errori se non inseriscono i valori corretti. – MarkeD

risposta

7

profondità Post-ordine prima passeggiata di elenco nidificato

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

funzione di sostituzione che restituisce elenco modificato piuttosto che mutare in atto

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

Esempio

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

Grazie per la risposta! Questo è così vicino, ma la struttura di output non è _quite_ uguale all'originale. È possibile modificarlo in modo che str (t) assomigli a str (postwalk (function (x) replace.kv (x, s), t))? – MarkeD

+0

corretto. Ho solo bisogno di una guardia in 'replace.kv' dato che stava costringendo tutto a una lista. Un'alternativa sarebbe semplicemente restituire 'x' invece di' f (x) 'nella funzione' postwalk', ma è più generale così com'è. Ho anche riscritto 'postwalk' usando' lapply', ma dovrebbe funzionare come prima. –

+0

Grazie! Una funzione generale era ciò che stavo cercando, mi piace la ricorsività post-passerella. – MarkeD

Problemi correlati