【问题标题】:Function to concatenate paths?连接路径的功能?
【发布时间】:2012-10-18 02:03:15
【问题描述】:

是否有现有的连接路径的函数?

我知道实现起来并不难,但仍然......除了处理尾随/(或\)之外,我还需要处理正确的操作系统路径格式检测(即我们是否写@ 987654323@ 或 /dir/file)。

正如我所说,我相信我知道如何实现它;问题是:我应该这样做吗?该功能是否已存在于现有 R 包中?

【问题讨论】:

    标签: r path concatenation


    【解决方案1】:

    是的,file.path()

    R> file.path("usr", "local", "lib")
    [1] "usr/local/lib"
    R> 
    

    对于包中的文件,还有同样有用的system.path()

    R> system.file("extdata", "date_time_zonespec.csv", package="RcppBDT")
    [1] "/usr/local/lib/R/site-library/RcppBDT/extdata/date_time_zonespec.csv"
    R> 
    

    这将得到文件extdata/date_time_zonespec.csv 而不管

    1. 安装包的位置,以及
    2. 操作系统

    非常方便。最后,还有

    R> .Platform$file.sep
    [1] "/"
    R> 
    

    如果您坚持手动操作。

    【讨论】:

    • 很好的答案。但是,该函数不处理尾随“/”,因此file.path("/home/user/","project") 导致无效/home/user//project。是否有其他功能,或者我应该自己做(虽然微不足道)?
    • 如果你从一个空字符串开始你会得到它:file.path("", "home", "user", "project") 产生"/home/user/project"
    • 请注意,/home/user//project/home/user/project 在 Unix 上都有效。你在什么操作系统上?
    • @flodel 呃... Linux。但我不知道。谢谢!它似乎在 Windows 上也有效(在 cmd.exe 上)!
    • 这可能是基本的 R 知识,但如果您已经拥有 yourlist=list("", "a", "b", "c") 并且想要将其转换为路径,do.call(file.path, yourlist)
    【解决方案2】:

    如果有人想要,这是我自己的函数path.cat。它的功能可以与 Python 的 os.path.join 相媲美,但它可以解释 ..

    使用此函数,您可以按层次构造路径,但与file.path 不同的是,您可以通过放置绝对路径来覆盖层次结构。而作为一个加糖,他可以把“..”放在路径中任何他喜欢的地方,意义很明显。

    例如

    • path.cat("/home/user1","project/data","../data2") 输出/home/user1/project/data2

    • path.cat("/home/user1","project/data","/home/user2/data") 输出/home/user2/data

    该函数仅使用斜杠作为路径分隔符,这很好,因为 R 透明地将它们转换为 Windows 机器上的反斜杠。

    library("iterators") # After writing this function I've learned, that iterators are very inefficient in R.
    library("itertools")
    
    #High-level function that inteligentely concatenates paths given in arguments
    #The user interface is the same as for file.path, with the exception that it understands the path ".."
    #and it can identify relative and absolute paths.
    #Absolute paths starts comply with "^\/" or "^\d:\/" regexp.
    #The concatenation starts from the last absolute path in arguments, or the first, if no absolute paths are given.
    path.cat<-function(...)
    {
      elems<-list(...)
      elems<-as.character(elems)
      elems<-elems[elems!='' && !is.null(elems)]
      relems<-rev(elems)
      starts<-grep('^[/\\]',relems)[1]
      if (!is.na(starts) && !is.null(starts))
      {
        relems<-relems[1:starts]
      }
      starts<-grep(':',relems,fixed=TRUE)
      if (length(starts)==0){
        starts=length(elems)-length(relems)+1
      }else{
        starts=length(elems)-starts[[1]]+1}
      elems<-elems[starts:length(elems)]
      path<-do.call(file.path,as.list(elems))
      elems<-strsplit(path,'[/\\]',FALSE)[[1]]
      it<-ihasNext(iter(elems))
      out<-rep(NA,length(elems))
      i<-1
      while(hasNext(it))
      {
        item<-nextElem(it)
        if(item=='..')
        {
          i<-i-1
        } else if (item=='' & i!=1) {
          #nothing
        } else   {
          out[i]<-item
          i<-i+1
        }
      }
      do.call(file.path,as.list(out[1:i-1]))
    }
    

    【讨论】:

    • 很酷的评论,但有一个重要的区别:normalizePath() 要求路径实际存在于 R 服务器上。这可能并不总是需要的。对我来说,这是一个重要的区别。 OTOH 手册说 normalizePath() 在 Windows 上将短名称转换为长名称。
    猜你喜欢
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-05
    • 2016-02-03
    相关资源
    最近更新 更多