2016-07-07 3 views
8

Учитывая произвольно вложенный список, как я могу найти, содержит ли список пустые списки? Рассмотрим следующий пример:Найти пустые списки во вложенном списке списков

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

Я попытался rapply, но пропускает через списки. Хотя я мог бы использовать lapply, мне нужно было знать уровень гнездования заранее. Для этого упражнения мне не нужно знать, где находится список (хотя это будет бонус), мне просто нужен способ определить, есть ли он.

+0

@MrFlick Да, это то, что я после –

ответ

8

насчет функции, как этот

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

В основном мы создаем рекурсивную функцию для поиска списков длины 0.

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

А вот модификация найти индекс пустого списка

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

Это должно вернуть вектор индекса, который вы можете использовать для поиска пустого список. Например

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

Если сам первый параметр является пустым списком, он будет возвращать 0

find_empty_list(list()) 
# 0 

и если нет пустого списка, он должен возвращать пустой вектор

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

Я решил, что рекурсия будет хорошим способом ее решить. Одна небольшая модификация - я бы использовал 'vapply (x, has_empty_list, logical (1))'. –

+0

@ sebastian-c добавил еще одну функцию, чтобы найти недостающий список, а также – MrFlick

+0

Спасибо @MrFlick. Один, чтобы найти пустые списки, отлично, но один, чтобы найти пустые списки, немного сложнее. Кажется, что у него проблемы с несколькими пустыми списками (кажется, для самого вложенного). –

5

Другим удобным вариантом для работы с вложенным списком является использование data.tree пакета:

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

кажется довольно медленным. – Triamus