Matt Bannert
Matt Bannert

Reputation: 28274

Determine level of nesting in R?

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

Upvotes: 21

Views: 5805

Answers (5)

Friede
Friede

Reputation: 8087

There is ldepth(l, DF.as.list = TRUE) from {collapse}:

lapply(list(l1, l2, l3), collapse::ldepth)
> lapply(list(l1, l2, l3), collapse::ldepth)
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3

where l1, l2, and l3 is copied from user Spacedman's answer.

Upvotes: 0

Joris C.
Joris C.

Reputation: 6244

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

Upvotes: 1

Manuel R
Manuel R

Reputation: 4145

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

Upvotes: 8

Spacedman
Spacedman

Reputation: 94307

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.

Upvotes: 27

Roland
Roland

Reputation: 132969

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" 

Upvotes: 2

Related Questions