Is there an easy way (i.e. a function) to determine the level of nesting in list?
I know there is str
which can be used to get this information. But is there something that simply gives back the result? And can I use such a function to get the names of all levels of alist (recursively) ?
Asked
Active
Viewed 5,162 times
21

Matt Bannert
- 27,631
- 38
- 141
- 207
-
1You could try `s <- (capture.output(str(mylist, nest.lev=1))[-1])` and then use string processing to capture the number of `..`s that start each element of `s`. (If I get 10 minutes later and there's no better answer by then, I'll give that a shot myself.) – Josh O'Brien Nov 17 '12 at 18:13
4 Answers
26
A little recursive function can do this for you:
depth <- function(this,thisdepth=0){
if(!is.list(this)){
return(thisdepth)
}else{
return(max(unlist(lapply(this,depth,thisdepth=thisdepth+1))))
}
}
If you've got package:testthat
, here's a test set:
l1=list(1,2,3)
l2=list(1,2,l1,4)
l3=list(1,l1,l2,5)
require(testthat)
expect_equal(depth(l1),1)
expect_equal(depth(l2),2)
expect_equal(depth(l3),3)
Apologies for using lower-case L in variable names. Readability fail.

Spacedman
- 92,590
- 12
- 140
- 224
-
17+1 -- A bit shorter would be `depth <- function(this) ifelse(is.list(this), 1L + max(sapply(this, depth)), 0L)` – flodel Nov 17 '12 at 19:59
-
1
-
Thanks guys. Very nice indeed. I am somewhat surprised that there is no base solution for this. – Matt Bannert Nov 19 '12 at 08:55
-
2list() returns -inf, quick fix: if(is.list(this) && length(this) == 0){return(0)} – kevin Feb 13 '19 at 13:45
7
You can now use depth()
from the purrr
package!
Note: currently the function is part of the development version of purrr
but will become part of the official CRAN version once the package gets a version bump

Manuel R
- 3,976
- 4
- 28
- 41
-
8I think its now in CRAN as `purrr::vec_depth`, but there's also `plotrix::listDepth` – Spacedman Mar 13 '18 at 10:36
-
`listDepth` was removed from the `plotrix` package in version 3.8-1. But +1 for `purrr::vec_depth`, which gets the job done. – dbc Sep 23 '21 at 15:14
2
If all elements are named, you could use this (from the code of unlist
):
mylist <- list(a=list(x=1),b=list(c=list(y=c(2,3)),d=c("a","b")))
names(.Internal(unlist(mylist, TRUE, TRUE)))
#[1] "a.x" "b.c.y1" "b.c.y2" "b.d1" "b.d2"

Roland
- 127,288
- 10
- 191
- 288
1
Another approach using rrapply()
in the rrapply
-package (extension of base rapply()
):
library(rrapply)
l1 <- list(1, 2, 3)
l2 <- list(1, 2, l1, 4)
l3 <- list(1, l1, l2, 5)
max(rrapply(l1, f = function(x, .xpos) length(.xpos), how = "unlist"))
#> [1] 1
max(rrapply(l2, f = function(x, .xpos) length(.xpos), how = "unlist"))
#> [1] 2
max(rrapply(l3, f = function(x, .xpos) length(.xpos), how = "unlist"))
#> [1] 3

Joris C.
- 5,721
- 3
- 12
- 27