2016-07-07 22 views
8

Dato un elenco nidificato arbitrariamente, come posso trovare se un elenco contiene elenchi vuoti? Si consideri il seguente esempio:Trova liste vuote nell'elenco di elenchi annidati

mylist <- list(list("foo", "bar", "baz", list(list())))

ho provato rapply, ma che salta attraverso le liste. Mentre potrei usare lapply, avrei bisogno di conoscere il livello di nidificazione in anticipo. Per questo esercizio, non ho bisogno di sapere dove sia la lista (anche se questo sarebbe un bonus), ho solo bisogno di un modo per rilevare se ce n'è uno.

+0

@MrFlick Sì, questo è quello che sto cercando –

risposta

8

Che dire di una funzione come questa

has_empty_list <- function(x) { 
    if(is.list(x)) { 
     if (length(x)==0) { 
      return(TRUE) 
     } else { 
      return(any(vapply(x, has_empty_list, logical(1)))) 
     } 
    } else { 
     return(FALSE) 
    } 
} 

In sostanza si crea una funzione ricorsiva per cercare liste di lunghezza 0.

has_empty_list(list(list("foo", "bar", "baz", list(list())))) 
# TRUE 
has_empty_list(list(list("foo", "bar", "baz", list(list(4))))) 
# FALSE 

Ed ecco una modifica per trovare l'indice della lista vuota

find_empty_list <- function(x, index=c()) { 
    if(is.list(x)) { 
     #list 
     if (length(x)==0) { 
      if (length(index)==0) { 
       return(0) 
      } else { 
       return(index) 
      } 
     } else { 
      m <- Map(find_empty_list, x, lapply(seq_along(x), function(i) append(index,i))) 
      # return the most deeply nested 
      return(m[[which.max(lengths(m))]]) 
     } 
    } else { 
     return(numeric()) 
    } 
} 

Questo dovrebbe restituire un vettore dell'indice che è possibile utilizzare per trovare il vuoto elenco. Ad esempio

(i <- find_empty_list(mylist)) 
# [1] 1 4 1 
mylist[[i]] 
# list() 

Se il primo parametro stesso è un elenco vuoto, esso ritorna 0

find_empty_list(list()) 
# 0 

e se non esiste un elenco vuoto, dovrebbe restituire un vettore vuoto

find_empty_list(list(1:3, list("c", a~b))) 
# numeric() 
+1

Ho pensato che la ricorsione sarebbe stata un buon modo per risolverlo. Una leggera modifica: userei 'vapply (x, has_empty_list, logical (1))'. –

+0

@ sebastian-c ha aggiunto un'altra funzione per trovare anche l'elenco mancante – MrFlick

+0

Grazie a @MrFlick. Quello per trovare le liste vuote è grande, ma quello per trovare le liste vuote è un po 'più complicato. Sembra avere problemi con più liste vuote (sembra essere per la più nidificata). –

5

Un'altra opzione utile per lavorare con l'elenco annidato è utilizzare il pacchetto data.tree:

library(data.tree) 
nodes <- as.Node(mylist) 
any(node$Get(function(node) length(as.list(node))) == 0) 
# [1] TRUE 
+0

sembra essere piuttosto lento. – Triamus

Problemi correlati