2013-03-13 2 views
3

Есть ли «встроенный»/эффективный и надежный способ проверки, являются ли объекты списка вложенными или нет?Проверьте, является ли список вложенным или нет

Чтобы прояснить мое понимание термина вложенной:

Flat или нет вложенного список

x.1 <- list(
    a=TRUE, 
    b=1:5 
) 

Вложенного список

x.2 <- list(
    a=list(a.1=list(a.1.1=TRUE)), 
    b=list(b.1=1:5) 
) 

Моей первая идея состояла в том, чтобы используйте комбинацию str, capture.output и регулярные выражения. Но все, что связано с регулярным выражением: довольно мощный, довольно рискованной на стороне робастности ;-) Так что я подумал, что есть что-то лучше там:

isNested <- function(x) { 
    if (class(x) != "list") { 
     stop("Expecting 'x' to be a list") 
    } 
    out <- FALSE 
    strout <- capture.output(str(x)) 
    idx <- grep("\\$.*List", strout) 
    if (length(idx)) { 
     out <- TRUE 
    } 
    return(out) 
} 

> isNested(x=x.1) 
[1] FALSE 
> isNested(x=x.2) 
[1] TRUE 

Второй подход любезно римской и Аруна:

isNested2 <- function(x) { 
    if (class(x) != "list") { 
     stop("Expecting 'x' to be a list") 
    } 
    out <- any(sapply(x, is.list)) 
    return(out) 
} 

> isNested2(x=x.1) 
[1] FALSE 
> isNested2(x=x.2) 
[1] TRUE 
+1

Что делать, если вы проверили свой первый список заказов, если список классов? Если да, то он вложен, иначе нет. Что-то в строках 'any (sapply (x.2, function (x) class (x) ==" list "))'. 'any (sapply (x.1, function (x) class (x) ==" list "))' возвращает FALSE. –

+1

'any (sapply (my_list, class) ==" list ")' – Arun

+0

Правильно, это было бы проще ;-) Спасибо, ребята! Внедрение вашего подхода в качестве второго подхода. Cheers – Rappster

ответ

6

Вы можете использовать функцию is.list:

any(sapply(x.1, is.list)) 
[1] FALSE 

any(sapply(x.2, is.list)) 
[1] TRUE 

В функции isNested:

isNested <- function(l) { 
    stopifnot(is.list(l)) 
    for (i in l) { 
    if (is.list(i)) return(TRUE) 
    } 
    return(FALSE) 
} 

Вместо тестирования всех элементов списка, функция прекращается, как только он обнаруживает вложенный список.

2

Попробуйте это:

isNested <- function(x) { 
    if (is.list(x)) 
     stop("Expecting 'x' to be a list") 

    any(unlist(lapply(x,is.list))) 
    } 
+0

Спасибо, что ответили и включили его в« мой контекст функции »! Давал его Свену, потому что это всего лишь немного более краткий. ура – Rappster

2

Вот еще один способ для удовольствия:

length(unlist(l, FALSE)) != length(unlist(l)) 

Или вариации на том, что:

!identical(unlist(l, FALSE), unlist(l)) 

Позволяет использовать параметр recursiveunlist(). С проверкой ошибок также, если вы хотите:

isNested <- function(l) { 
    if (!is.list(l)) stop("Not a list.") 
    !identical(unlist(l, FALSE), unlist(l)) 
}