我想在字符串中的特定位置插入一个额外的字符(或新字符串)。例如,我想在d
的第四个位置插入abcefg
以获取abcdefg
。
现在我正在使用:
old <- "abcefg"
n <- 4
paste(substr(old, 1, n-1), "d", substr(old, n, nchar(old)), sep = "")
我可以为这个任务编写一个单行的简单函数,但我很好奇是否有现有函数。
答案 0 :(得分:55)
您可以使用正则表达式和gsub
执行此操作。
gsub('^([a-z]{3})([a-z]+)$', '\\1d\\2', old)
# [1] "abcdefg"
如果要动态执行此操作,可以使用paste
创建表达式:
letter <- 'd'
lhs <- paste0('^([a-z]{', n-1, '})([a-z]+)$')
rhs <- paste0('\\1', letter, '\\2')
gsub(lhs, rhs, old)
# [1] "abcdefg"
根据DWin的评论,您可能希望这更加通用。
gsub('^(.{3})(.*)$', '\\1d\\2', old)
这样任何三个字符都匹配而不是小写。 DWin还建议使用sub
代替gsub
。这样您就不必担心^
,因为sub
只会匹配第一个实例。但我喜欢在正则表达式中明确表达,只是在我理解它们时转向更一般的表达式,并且需要更多的通用性。
正如Greg Snow所说,你可以使用另一种形式的正则表达式来查看匹配:
sub( '(?<=.{3})', 'd', old, perl=TRUE )
并且还可以使用gsub
而不是sprintf
来构建我的动态paste0
:
lhs <- sprintf('^([a-z]{%d})([a-z]+)$', n-1)
或他的sub
正则表达式:
lhs <- sprintf('(?<=.{%d})',n-1)
答案 1 :(得分:16)
stringi
包裹再次救援!现有的解决方案中最简单,最优雅的解决方案。
stri_sub
函数允许您提取字符串的一部分并替换它的一部分,如下所示:
x <- "abcde"
stri_sub(x, 1, 3) # from first to third character
# [1] "abc"
stri_sub(x, 1, 3) <- 1 # substitute from first to third character
x
# [1] "1de"
但如果你这样做:
x <- "abcde"
stri_sub(x, 3, 2) # from 3 to 2 so... zero ?
# [1] ""
stri_sub(x, 3, 2) <- 1 # substitute from 3 to 2 ... hmm
x
# [1] "ab1cde"
然后不会删除任何字符,但会插入新字符。这不酷吗? :)
答案 2 :(得分:8)
@ Justin的回答是因为它的灵活性我实际上是这样做的,但this也可能是一种有趣的方法。
您可以将字符串视为“固定宽度格式”,并指定要插入字符的位置:
paste(read.fwf(textConnection(old),
c(4, nchar(old)), as.is = TRUE),
collapse = "d")
使用sapply
时输出特别好,因为您可以将原始字符串视为“名称”。
newold <- c("some", "random", "words", "strung", "together")
sapply(newold, function(x) paste(read.fwf(textConnection(x),
c(4, nchar(x)), as.is = TRUE),
collapse = "-WEE-"))
# some random words strung together
# "some-WEE-NA" "rand-WEE-om" "word-WEE-s" "stru-WEE-ng" "toge-WEE-ther"
答案 3 :(得分:3)
您执行此操作的原始方式(即将字符串拆分为索引并粘贴插入的文本)可以制作为通用函数,如下所示:
split_str_by_index <- function(target, index) {
index <- sort(index)
substr(rep(target, length(index) + 1),
start = c(1, index),
stop = c(index -1, nchar(target)))
}
#Taken from https://stat.ethz.ch/pipermail/r-help/2006-March/101023.html
interleave <- function(v1,v2)
{
ord1 <- 2*(1:length(v1))-1
ord2 <- 2*(1:length(v2))
c(v1,v2)[order(c(ord1,ord2))]
}
insert_str <- function(target, insert, index) {
insert <- insert[order(index)]
index <- sort(index)
paste(interleave(split_str_by_index(target, index), insert), collapse="")
}
使用示例:
> insert_str("1234567890", c("a", "b", "c"), c(5, 9, 3))
[1] "12c34a5678b90"
这允许您在索引向量给出的位置插入字符向量。 split_str_by_index
和interleave
函数也可以自行使用。
修改:
我修改了代码以允许任何顺序的索引。之前,索引需要按升序排列。
答案 4 :(得分:1)
我花了一些时间来理解正则表达式,然后我找到了我的方式
最终结果是
old <- "89580000"
gsub('^([0-9]{5})([0-9]+)$', '\\1-\\2', old)
答案 5 :(得分:0)
我已经创建了一个名为substr1
的自定义函数来处理字符串中的字符串提取,替换和插入。在每个会话开始时运行这些代码。如果需要改进,请随意尝试并告诉我。
# extraction
substr1 <- function(x,y) {
z <- sapply(strsplit(as.character(x),''),function(w) paste(na.omit(w[y]),collapse=''))
dim(z) <- dim(x)
return(z) }
# substitution + insertion
`substr1<-` <- function(x,y,value) {
names(y) <- c(value,rep('',length(y)-length(value)))
z <- sapply(strsplit(as.character(x),''),function(w) {
v <- seq(w)
names(v) <- w
paste(names(sort(c(y,v[setdiff(v,y)]))),collapse='') })
dim(z) <- dim(x)
return(z) }
# demonstration
abc <- 'abc'
substr1(abc,1)
# "a"
substr1(abc,c(1,3))
# "ac"
substr1(abc,-1)
# "bc"
substr1(abc,1) <- 'A'
# "Abc"
substr1(abc,1.5) <- 'A'
# "aAbc"
substr1(abc,c(0.5,2,3)) <- c('A','B')
# "AaB"