2016-06-16 23 views
7

ho un elemento nidificato come questoRimozione di elementi di una lista R nidificato per nome

> x <- list(a=list(from="me", id="xyz"), b=list(comment=list(list(message="blabla", id="abc"), list(message="humbug", id="jkl"))), id="123") 
> str(x) 
List of 3 
$ a :List of 2 
    ..$ from: chr "me" 
    ..$ id : chr "xyz" 
$ b :List of 1 
    ..$ comment:List of 2 
    .. ..$ :List of 2 
    .. .. ..$ message: chr "blabla" 
    .. .. ..$ id  : chr "abc" 
    .. ..$ :List of 2 
    .. .. ..$ message: chr "humbug" 
    .. .. ..$ id  : chr "jkl" 
$ id: chr "123" 

Come posso rimuovere tutti gli elementi con nome id a tutti i livelli della lista? vale a dire il risultato atteso è

> str(x) 
List of 2 
$ a:List of 1 
    ..$ from: chr "me" 
$ b:List of 1 
    ..$ comment:List of 2 
    .. ..$ :List of 1 
    .. .. ..$ message: chr "blabla" 
    .. ..$ :List of 1 
    .. .. ..$ message: chr "humbug" 

Solutions utilizzando rlist pacchetto sarebbe particolarmente gradito, ma sono contento di tutto ciò che funziona.

+0

Potete mostrare previsto in uscita? (usa 'dput' invece di' str') – Sotos

+0

output atteso è il secondo blocco di quotazione sopra – Ricky

+0

'dput' è il tuo amico –

risposta

3

ricorsione è anche come ho fatto:

# recursive function to remove name from all levels of list 
stripname <- function(x, name) { 
    thisdepth <- depth(x) 
    if (thisdepth == 0) { 
     return(x) 
    } else if (length(nameIndex <- which(names(x) == name))) { 
     x <- x[-nameIndex] 
    } 
    return(lapply(x, stripname, name)) 
} 

# function to find depth of a list element 
# see http://stackoverflow.com/questions/13432863/determine-level-of-nesting-in-r 
depth <- function(this, thisdepth=0){ 
    if (!is.list(this)) { 
     return(thisdepth) 
    } else{ 
     return(max(unlist(lapply(this,depth,thisdepth=thisdepth+1))))  
    } 
} 


str(stripname(x, "id")) 
## List of 2 
## $ a:List of 1 
## ..$ from: chr "me" 
## $ b:List of 1 
## ..$ comment:List of 2 
## .. ..$ :List of 1 
## .. ..$ :List of 1 
## .. .. ..$ message: chr "blabla" 
## .. .. ..$ message: chr "humbug" 
2

Prova una funzione ricorsiva nelle vene della

f <- function(i) 
    lapply(i, function(x) 
    if (is.list(x)) { 
     if(!is.null(names(x))) f(x[names(x)!="id"]) else f(x) 
    } else x 
) 
str(f(x[names(x)!="id"])) 
# List of 2 
# $ a:List of 1 
# ..$ from: chr "me" 
# $ b:List of 1 
# ..$ comment:List of 2 
# .. ..$ :List of 1 
# .. .. ..$ message: chr "blabla" 
# .. ..$ :List of 1 
# .. .. ..$ message: chr "humbug" 
+0

Questo funzionerà solo se la profondità della lista è 2 come nell'esempio. Se ci sono elementi più profondi, abbiamo bisogno di cose ricorsive - magari riscrivere con 'rapply' (non ci sono riusciti) –

Problemi correlati