我看到Gabor G.针对this question提交的有关字符串歧义消除的巧妙代码。他的回答(稍作修改)是:
uniqName <- function(x){
thenames <- ave(x,x,FUN = function(z){
znam <- if (length(z) == 1) z else sprintf("%s%02d", z, seq_along(z))
return(znam)
})
return(thenames)
}
我想去一个“不可见的”版本,并试图提出一个紧凑的函数,该函数将N个空格附加到名称的第(N + 1)个出现位置。 (Gabor的代码会计算一个整数并将其附加,因此附加的字符数是恒定的)。我能做的最好的就是以下笨拙的函数(“ fatit”)
spacify <- function (x){
fatit <-function(x){
k = vector(length=length(x))
for(jp in 1:length(x)){
k[jp]=sprintf('%s%s',x[jp],paste0(rep(' ',jp),collapse=''))
}
return(k)
}
spaceOut <- ave(x,x, FUN = function(z) if (length(z) == 1) z else fatit(z) )
return(spaceOut)
}
是否有一些更简洁,更紧凑的方法来基于length(z)
函数中的fatit
设置要附加的字符数?
注意:
uniqName(foo)
[1] "a01" "b01" "c01" "a02" "b02" "a03" "c02" "d" "e"
spacify(foo)
[1] "a " "b " "c " "a " "b " "a " "c " "d" "e"
答案 0 :(得分:2)
我们可以利用make.unique
的优势,方法是去除使字符唯一的数字,并使用(... + 1)作为要添加的字符数的参考,即
i1 <- as.numeric(gsub('\\D+', '', make.unique(x)))
i1[is.na(i1)] <- 0 #because where there is no number it returns NA
paste0(x, sapply(i1 + 1, function(i) paste(rep(' ', each = i), collapse = '')))
#[1] "a " "b " "c " "a " "b " "a " "c " "d " "e "
答案 1 :(得分:1)
我们可以利用stri_pad_right
中的stringi
函数:
library(stringi)
f <- function(x){
ave(x, x, FUN = function(z){
if(length(z) == 1) z else stri_pad_right(z, nchar(z[1]) + seq_along(z))
})
}
x <- c('a', 'b', 'c', 'a', 'b', 'a', 'c', 'd', 'e')
f(x)
# [1] "a " "b " "c " "a " "b " "a " "c " "d" "e"
使用stringr::str_pad(..., side = 'right')
在概念上是相似的。