我正在尝试替换字符串向量的所有元素中的字符,其中字符不同,但始终与字符串的开头或结尾有一定距离。我可以成功使用substr
来替换字符串开头的字符。我试图使用包str_sub
中的stringr
来替换sting末尾的字符(因为它允许向后计数负数)。它替换了字符,但是对于第一个元素之后的所有元素,它将字符右边的所有元素替换为第一个元素的字符串结尾:
> require(stringr)
> x <- c("A'B'C","E!FG@H","I$JKL&M")
> substr(x,2,2) <- ":"
> x
[1] "A:B'C" "E:FG@H" "I:JKL&M"
> str_sub(x,-2,-2) <- ":"
> x
[1] "A:B:C" "E:FG:C" "I:JKL:C"
答案 0 :(得分:6)
试试这个:
require(stringr)
x <- c("A'B'C","E!FG@H","I$JKL&M")
substr(x,2,2) <- ":"
str_sub(x, rep(-2, length(x)), rep(-2, length(x))) <- ":"
它的行为是因为str_sub<-
将str_sub(x, start, end)
的结果传递给str_c,这就是崩溃对你来说错误的地方。
源代码中的函数是:
"str_sub<-" <- function(string, start = 1L, end = -1L, value) {
str_c(
str_sub(string, end = start - 1L),
value,
ifelse(end == -1L, "", str_sub(string, start = end + 1L)))
}
所以我们实际上将三个参数传递给str_c
函数,一个或多个字符向量,一个插入字符串和一个折叠参数(ifelse位)。如果不使用赋值函数只运行str_sub
的结果是(如果我们已经运行了第一个str_sub:
> (test.string <- str_sub(x, start = 1L, end = -2 - 1L)) #start defaults to 1L
[1] "A:B" "E:FG" "I:JKL"
> replace.string <- ":"
> (collapse.string <- ifelse(end == -1L, "", str_sub(string, start = end + 1L)))
[1] "C"
> str_c(test.string, replace.string, collapse.string)
[1] "A:B:C" "E:FG:C" "I:JKL:C"
首先,我们将所有要替换的符号左侧的所有内容保存,然后我们重新设置折叠参数。折叠参数有点有趣,如果你看一下str_c的文档,你会发现它说的是
如果折叠是......非''NULL',则在每行的末尾插入该字符串,并将整个矩阵折叠为单个字符串。
这就是这里发生的事情,当我们替换字符串时,它会将collapse参数添加到每个字符串的末尾。
但实际上,如果没有使用ifelse函数,这将有效,因为如果没有ifelse,str_sub(string, start = end + 1L)
将返回[1] "C" "H" "M"
而不是仅仅取第一个索引,&#34; C& #34 ;.
所以这就是为什么当我们添加c(-2,-2,-2)的开始和结束值时,我们可以得到正确的答案:
> (test.string <- str_sub(x, start = 1L, end = c(-2, -2, -2) - 1L)) #start defaults to 1L
[1] "A:B" "E:FG" "I:JKL"
> replace.string <- ":"
> (collapse.string <- ifelse(end == -1L, "", str_sub(string, start = c(-2, -2, -2) + 1L)))
[1] "C" "H" "M"
> str_c(test.string, replace.string, collapse.string)
[1] "A:B:C" "E:FG:C" "I:JKL:C"
答案 1 :(得分:1)
不确定str_sub
的问题是什么,但你可以自己动手:
my_sub <- function(x,n,s) {
N <- nchar(x)-n+1
substr(x,n,n) <- substr(x,N,N) <- s
x
}
my_sub(x,2,":")
# [1] "A:B:C" "E:FG:H" "I:JKL:M"