Function to concatenate paths?

RPathConcatenation

R Problem Overview


Is there an existing function to concatenate paths?

I know it is not that difficult to implement, but still... besides taking care of trailing / (or \) I would need to take care of proper OS path format detection (i.e. whether we write C:\dir\file or /dir/file).

As I said, I believe I know how to implement it; the question is: should I do it? Does the functionality already exist in existing R package?

R Solutions


Solution 1 - R

Yes, file.path()

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

There is also the equally useful system.path() for files in a package:

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

which will get the file extdata/date_time_zonespec.csv irrespective of

  1. where the package is installed, and
  2. the OS

which is very handy. Lastly, there is also

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

if you insist on doing it manually.

Solution 2 - R

In case anyone wants, this is my own function path.cat. Its functionality is comparable with Python's os.path.join with the extra sugar, that it interprets the ...

With this function, you can construct paths hierarchically, but unlike the file.path, you leave the user the ability to override the hierarchy by putting an absolute path. And as an added sugar, he can put the ".." wherever he likes in the path, with obvious meaning.

e.g.

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

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

The function works only with slashes as path separator, which is fine, since R transparently translates them to backslashes on Windows machine.

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]))
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAdam RyczkowskiView Question on Stackoverflow
Solution 1 - RDirk EddelbuettelView Answer on Stackoverflow
Solution 2 - RAdam RyczkowskiView Answer on Stackoverflow