Jeśli ktoś chce, to jest moja własna funkcja path.cat
. Jego funkcjonalność jest porównywalna z Pythonem os.path.join
z dodatkowym cukrem, który interpretuje ..
.
Za pomocą tej funkcji można konstruować ścieżki hierarchicznie, ale w przeciwieństwie do file.path
, użytkownik pozostawia możliwość nadpisania hierarchii, umieszczając bezwzględną ścieżkę. Jako dodatek do cukru może umieścić "..." wszędzie, gdzie mu się podoba, z oczywistym znaczeniem.
np.
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
Funkcja działa tylko z ukośniki jako separator ścieżki, który jest w porządku, ponieważ R przejrzyście tłumaczy je na ukośniki na komputerze z systemem 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]))
}
Świetna odpowiedź. Ale funkcja nie zajmuje się końcowym "/", więc 'file.path ("/home/user/"," project ")' powoduje niepoprawne '/ home/user // project'. Czy istnieje inna funkcja, czy też powinienem to zrobić sam (choćby trywialnie)? –
Otrzymasz, jeśli zaczniesz od pustego ciągu: 'file.path (" "," home "," user "," project ")' produkuje '"/home/user/project "' –
Zwróć uwagę, że '/ home/user // project' i '/ home/user/project' są poprawne w systemie Unix. Na jakim systemie operacyjnym jesteś? – flodel