web-dev-qa-db-fra.com

Fonction de concaténation de chemins?

Existe-t-il une fonction existante pour concaténer les chemins?

Je sais que ce n'est pas si difficile à mettre en œuvre, mais quand même ... en plus de prendre soin de suivre / (ou \) Je devrais m'occuper de la bonne détection du format du chemin du système d'exploitation (c'est-à-dire si nous écrivons C:\dir\file ou /dir/file).

Comme je l'ai dit, je crois que je sais comment le mettre en œuvre; la question est: dois-je le faire? La fonctionnalité existe-t-elle déjà dans le package R existant?

54
Adam Ryczkowski

Oui, file.path()

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

Il existe également la system.path() tout aussi utile pour les fichiers d'un 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> 

qui obtiendra le fichier extdata/date_time_zonespec.csv indépendamment de

  1. où le package est installé, et
  2. l'OS

ce qui est très pratique. Enfin, il y a aussi

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

si vous insistez pour le faire manuellement.

92
Dirk Eddelbuettel

Au cas où quelqu'un le voudrait, c'est ma propre fonction path.cat. Sa fonctionnalité est comparable à celle de Python os.path.join avec le sucre supplémentaire, qu'il interprète le ...

Avec cette fonction, vous pouvez construire des chemins hiérarchiquement, mais contrairement au file.path, Vous laissez à l'utilisateur la possibilité de remplacer la hiérarchie en mettant un chemin absolu. Et comme sucre ajouté, il peut mettre le ".." où il veut sur le chemin, avec une signification évidente.

par exemple.

  • 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

La fonction ne fonctionne qu'avec des barres obliques comme séparateur de chemin, ce qui est bien, car R les traduit de manière transparente en barres obliques inverses sur la machine 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