web-dev-qa-db-ja.com

パスを連結する関数?

パスを連結する既存の関数はありますか?

実装するのはそれほど難しくないことはわかっていますが、それでも...末尾の/(または\)適切なOSパス形式の検出に注意する必要があります(つまり、C:\dir\fileまたは/dir/file)。

私が言ったように、私はそれを実装する方法を知っていると信じています。質問は次のとおりです。機能は既存のRパッケージに既に存在しますか?

54
Adam Ryczkowski

はい、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. oS

これは非常に便利です。最後に、もあります

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

手動で行うことを主張する場合。

92

誰もが望む場合、これは私自身の関数_path.cat_です。その機能はPythonの _os.path.join_ に匹敵し、追加の砂糖を使用して、_.._を解釈します。

この関数を使用すると、パスを階層的に構築できますが、_file.path_とは異なり、絶対パスを設定することでユーザーが階層をオーバーライドできるようにします。そして、追加の砂糖として、彼はパスの好きなところに「..」を明白な意味で置くことができます。

例えば.

  • 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_

この関数は、パスセパレーターとしてスラッシュのみで機能します。これは、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]))
}
_
3
Adam Ryczkowski