Rappster - 6 months ago 23
R Question

# Check if a list is nested or not

Is there a "built-in"/efficient and robust way to check if list objects are nested or not?

To clarify my understanding of the term nested:

Flat or not-nested list

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

Nested list

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

My first idea was to use a combination of
`str`
,
`capture.output`
and regular expressions. But as everything related to regular expression: pretty powerful, pretty risky on the robustness side ;-) So I wondered if there's something better out there:

``````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
``````

Second approach courtesy of Roman and Arun:

``````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
``````

You can use the `is.list` function:

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

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

As a function `isNested`:

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

Instead of testing all list elements, the function stops as soon as it detects a nested list.