Функция для конкатенации путей?
Существует ли существующая функция для конкатенации путей?
Я знаю, что это не так сложно реализовать, но все же... кроме того, чтобы позаботиться о завершении /
(или \
), мне нужно будет позаботиться о правильном определении формата пути ОС (т.е. пишем ли мы C:\dir\file
или /dir/file
).
Как я уже сказал, я считаю, что знаю, как его реализовать; вопрос: должен ли я это делать? Функциональность уже существует в существующем пакете R?
Ответы
Ответ 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
независимо от
- где установлен пакет, и
- ОС
что очень удобно. Наконец, есть и
R> .Platform$file.sep
[1] "/"
R>
если вы настаиваете на том, чтобы делать это вручную.
Ответ 2
В случае, если кто-то хочет, это моя собственная функция 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]))
}