【问题标题】:Representing a directory tree as a recursive list将目录树表示为递归列表
【发布时间】:2012-12-20 17:23:33
【问题描述】:

我被某项任务困住了。我想要的是一个函数,给定一个目录路径,它会返回一个递归列表作为输出。

输出的格式应该是 myList$dir$subdir$subdir$fullFilePath

所以基本上我想将目录树表示为某个列表。我获取了所有文件,获取了每个文件的所有子目录,但我不知道如何将它们全部放入具有多个级别的列表中。

【问题讨论】:

    标签: r list recursive-datastructures directory-tree


    【解决方案1】:

    这是一个使用递归的解决方案:

    tree.list <- function(file.or.dir) {
        isdir <- file.info(file.or.dir)$isdir
        if (!isdir) {
            out <- file.or.dir
        } else {
            files <- list.files(file.or.dir, full.names   = TRUE,
                                             include.dirs = TRUE)
            out <- lapply(files, tree.list)
            names(out) <- basename(files)
        }
        out
    }
    

    我这里在一个小目录上测试过

    test.dir <- tree.list("./test")
    test.dir
    # $a
    # $a$`1.txt`
    # [1] "./test/a/1.txt"
    # 
    # $a$aa
    # $a$aa$`2.txt`
    # [1] "./test/a/aa/2.txt"
    # 
    # $b
    # $b$`3.txt`
    # [1] "./test/b/3.txt"
    

    如果这对于您的需求来说太慢了,我会考虑将所有文件读入一个调用 list.filesrecursive = TRUE 然后做一些解析。

    【讨论】:

    • 谢谢!这太优雅了,让人心疼。
    • 暂时不会太慢。对于解析 - 我仍然不知道如何在解析后制作递归列表。在 strsplit 之后我会有类似的东西:list(dir=myDir, subdir1=mySubdir1, subdir2=mySubdir2, file=myFile)。 For 循环不适用于 list[["myDir"]][[mySubdir1]][[mySubdir2]][[myFile]]
    【解决方案2】:

    这是一个丑陋的 hack。

    mypath <- 'a/b/c/d'
    
    
    makelist <- function(filepath, fsep = '/'){
    
      unlisted <- unlist(strsplit(filepath, fsep))
    
      nsubs <- length(unlisted)
    
      mylistcall <- paste(paste(rep('list(', nsubs), unlisted, collapse = '='), 
        '= NULL', paste(rep(')', nsubs), collapse = ''))
    
    
      mylist <- eval(parse(text = mylistcall))
      return(mylist)
      }
    
    makelist(mypath)
    
    $a
    $a$b
    $a$b$c
    $a$b$c$d
    NULL   
    

    回忆

    fortune(106)
    
    If the answer is parse() you should usually rethink the question.
       -- Thomas Lumley
          R-help (February 2005)
    

    但是,在这种情况下,我会说我应该重新考虑答案。

    【讨论】:

    【解决方案3】:

    这是@flodel 使用purrr 包的精彩解决方案的一个较短变体:

    library( purrr )
    tree_list <- function( file_or_dir ) {
      f <- partial(list.files, full.names=TRUE, include.dirs=TRUE) %>%
             compose(tree_list, .)
      file_or_dir %>% set_names( basename(.) ) %>% map_if(dir.exists, f)
    }
    

    第一行定义了一个函数f,它使用list.files( ..., full.names=TRUE, include.dirs=TRUE)扩展其参数,然后将tree_list()应用于扩展。

    第二行将定义的函数f 应用于原始参数中的所有目录。

    【讨论】:

    • 我希望我能在努力之前看到这个!
    猜你喜欢
    • 1970-01-01
    • 2019-04-23
    • 2014-10-03
    • 2011-03-10
    • 1970-01-01
    • 2011-01-28
    • 1970-01-01
    • 2018-11-06
    相关资源
    最近更新 更多