Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

R – is there a function similar to list.dirs which returns a named nested list instead of the character vector?

First let’s run this function to create the example folder structure:

c("Level1/Level1A/Level1AA", 
  "Level1/Level1A/Level1AB", 
  "Level1/Level1B/Level1BA", 
  "Level1/Level1B/Level1BB",
  "Level2/Level2A/Level2AA", 
  "Level2/Level2A/Level2AB", 
  "Level2/Level2B/Level2BA", 
  "Level2/Level2B/Level2BB") %>% 
  map(dir.create, recursive = T)

Now let’s imagine that this folder structure wasn’t created by R but given to us as is.

If I run list.dirs on the parent folder, I will get:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

 [1] "."                         "./Level1"                  "./Level1/Level1A"          "./Level1/Level1A/Level1AA" "./Level1/Level1A/Level1AB"
 [6] "./Level1/Level1B"          "./Level1/Level1B/Level1BA" "./Level1/Level1B/Level1BB" "./Level2"                  "./Level2/Level2A"         
[11] "./Level2/Level2A/Level2AA" "./Level2/Level2A/Level2AB" "./Level2/Level2B"          "./Level2/Level2B/Level2BA" "./Level2/Level2B/Level2BB"

However, instead of this character vector, I wish to get a named nested list like this:

list(Level1 = list(Level1A = list("Level1AA",
                                  "Level1AB"),
                   Level1B = list("Level1BA",
                                  "Level1BB")),
     Level2 = list(Level2A = list("Level2AA",
                                  "Level2AB"),
                   Level2B = list("Level2BA",
                                  "Level2BB")))

What is the easiest way to achieve this?

>Solution :

You could use recursion in base R as follows:

my_fun <- function(x){
  ssplit <- function(x){
    if(is.data.frame(x))
      if(ncol(x)>1) c(by(x[-1], x[1], ssplit)) else as.list(x[[1]])
    else lapply(x, ssplit)
  }
  x <- grep("/", sub("^\\W+", "", x), value = TRUE)
  ssplit(read.table(text = x, sep='/', fill = TRUE, header = FALSE))
}

s <- c("Level1/Level1A/Level1AA", "Level1/Level1A/Level1AB", 
           "Level1/Level1B/Level1BA", "Level1/Level1B/Level1BB", "Level2/Level2A/Level2AA", 
           "Level2/Level2A/Level2AB", "Level2/Level2B/Level2BA",  "Level2/Level2B/Level2BB")

    my_fun(s)

$Level1
$Level1$Level1A
$Level1$Level1A[[1]]
[1] "Level1AA"

$Level1$Level1A[[2]]
[1] "Level1AB"


$Level1$Level1B
$Level1$Level1B[[1]]
[1] "Level1BA"

$Level1$Level1B[[2]]
[1] "Level1BB"



$Level2
$Level2$Level2A
$Level2$Level2A[[1]]
[1] "Level2AA"

$Level2$Level2A[[2]]
[1] "Level2AB"


$Level2$Level2B
$Level2$Level2B[[1]]
[1] "Level2BA"

$Level2$Level2B[[2]]
[1] "Level2BB"
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading