R: Recursive function in deeply nested list: Accessing level of hierarchy

会有一股神秘感。 提交于 2021-01-28 06:44:29

问题


Out of interest and as a thought exercise, I was aiming to replicate the tree function from the windows command line in R. tree generates ASCII trees similar to the following example (taken from here and modified). If n is the hierarchical level, note that each file or folder has (n-1)*3 spaces, followed by +---

+---Desktop
+---Documents
    +---Custom Office Templates
    +---Fiddler2
        +---Captures
            +---Requests
            +---Responses
        +---Scripts
+---Favorites
    +---Links

I use list.files() to extract the filenames (albeit this function ignores empty directories) and the recursive function dir_tree() (inspired by this answer) to capture the hierarchy in a nested list.

library(purrr)
library(stringr)
dirs <- list.files(recursive = TRUE) 

# To create a reproducible example, I create dirs manually
dirs <- c("Desktop",
          "Documents",
          "Documents/Custom Office Templates",
          "Documents/Fiddler2",
          "Documents/Fiddler2/Captures",
          "Documents/Fiddler2/Captures/Requests",
          "Documents/Fiddler2/Captures/Responses",
          "Documents/Fiddler2/Scripts",
          "Documents/Favorites",
          "Documents/Favorites/Links"
)

dir_tree <- function(dirs) {
  first <- map_chr(str_split(dirs,"/"),~.x[1])
  rest  <- map_chr(str_split(dirs,"/"),~paste(.x[-1],collapse = "/"))
  zi    <- nchar(dirs) == 0L 
  myli <- split(rest[!zi], first[!zi])
  map(myli, ~dir_tree(.x))
}

# creates a nested list
dir_nl <- dir_tree(dirs)

str(dir_nl)

## List of 2
##  $ Desktop  : Named list()
##  $ Documents:List of 3
##   ..$ Custom Office Templates: Named list()
##   ..$ Favorites              :List of 1
##   .. ..$ Links: Named list()
##   ..$ Fiddler2               :List of 2
##   .. ..$ Captures:List of 2
##   .. .. ..$ Requests : Named list()
##   .. .. ..$ Responses: Named list()
##   .. ..$ Scripts : Named list()

All I need to do now is to walk recursively through the nested list and print the names, prepending it with (n-1)*3 spaces and +---. The Question I have is: How do I retrieve n, i.e. the hierarchical level!?

recursive_print <- function(dir_nl){
  imap(dir_nl,function(x,y){
    if(is.list(x)){
      print(paste("+---",y))
      recursive_print(x)
    } 
  })
}


recursive_print(dir_nl) %>% invisible()

## [1] "+--- Desktop"
## [1] "+--- Documents"
## [1] "+--- Custom Office Templates"
## [1] "+--- Favorites"
## [1] "+--- Links"
## [1] "+--- Fiddler2"
## [1] "+--- Captures"
## [1] "+--- Requests"
## [1] "+--- Responses"
## [1] "+--- Scripts"

回答1:


I haven't been able to solve it myself, but found a package that does it for me. This kind of defeats the purpose of learning recursive functions, but I'll place this here in case anyone lands here.

library(data.tree)

tree <- FromListSimple(dir_nl)

print(tree)

##                          levelName
## 1  Root                           
## 2   ¦--Desktop                    
## 3   °--Documents                  
## 4       ¦--Custom Office Templates
## 5       ¦--Favorites              
## 6       ¦   °--Links              
## 7       °--Fiddler2               
## 8           ¦--Captures           
## 9           ¦   ¦--Requests       
## 10          ¦   °--Responses      
## 11          °--Scripts

And for the record, data.tree has a method to directly parse a string of filepaths into a tree, so dir_tree() becomes obsolete.

as.Node(data.frame(paths = dirs),pathName = "paths")

##                     levelName
## 1 Desktop                    
## 2  ¦--Custom Office Templates
## 3  ¦--Fiddler2               
## 4  ¦   ¦--Captures           
## 5  ¦   ¦   ¦--Requests       
## 6  ¦   ¦   °--Responses      
## 7  ¦   °--Scripts            
## 8  °--Favorites              
## 9      °--Links


来源:https://stackoverflow.com/questions/65819395/r-recursive-function-in-deeply-nested-list-accessing-level-of-hierarchy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!