2017-07-25 57 views
3

比方说,我有两个向量像这样:在R替换字符串模式和更换两个向量

a <- c("this", "is", "test") 
b <- c("that", "was", "boy") 

我也有像这样一个字符串变量:

string <- "this is a story about a test" 

我想替换值在字符串,以便它变成以下内容:

string <- "that was a story about a boy" 

我可以使用for循环做到这一点,但我希望这是v ectorized。我应该怎么做?

回答

8

如果你打开使用非基本包,stringi真的会很好地工作在这里:

stringi::stri_replace_all_fixed(string, a, b, vectorize_all = FALSE) 
#[1] "that was a story about a boy" 

注意,这也以同样的方式对长度> 1

的输入字符串

为了安全起见,可以适应这一点 - 类似于R用户的答案 - 更换前检查单词边界:

stri_replace_all_regex(string, paste0("\\b", a, "\\b"), b, vectorize_all = FALSE) 

这将确保你不会意外例如,替换hishwas

3
> library(stringi) 
> stri_replace_all_regex(string, "\\b" %s+% a %s+% "\\b", b, vectorize_all=FALSE) 
#[1] "that was a story about a boy" 
4

以下是一些解决方案。即使string是一个字符串的字符向量,它们每个都会工作,在这种情况下,将在其每个组件上进行替换。

1)减少这不使用包。

Reduce(function(x, i) gsub(paste0("\\b", a[i], "\\b"), b[i], x), seq_along(a), string) 
## [1] "that was a story about a boy" 

2)gsubfngsubfn就像gsub但更换参数可以是取代(或某些其他对象)的列表。

library(gsubfn) 

gsubfn("\\w+", setNames(as.list(b), a), string) 
## [1] "that was a story about a boy" 

3)环这不是矢量但是已经添加用于比较。没有包被使用。

out <- string 
for(i in seq_along(a)) out <- gsub(paste0("\\b", a[i], "\\b"), b[i], out) 
out 
## [1] "that was a story about a boy" 

注:有周期是否是可能的一些问题。例如,如果

a <- c("a", "A") 
b <- rev(a) 

做我们想要

  • “一” 要与 “A”,然后回到 “A” 再次,或
  • “A” 和 “A” 代替被交换。

上面显示的所有解决方案都假定为第一种情况。如果我们想要第二种情况,那么执行两次操作。我们将说明与(2),因为它是最短的,但同样的想法适用于所有这些:

# swap "a" and "A" 
a <- c("a", "A") 
b <- rev(a) 

tmp <- gsubfn("\\w+", setNames(as.list(seq_along(a)), a), string) 
gsubfn("\\w+", setNames(as.list(b), seq_along(a)), tmp) 
## [1] "this is A story about A test" 
+0

不错!我还没有接触过Reduce。非常感谢。 – hjms

+0

已经添加了关于周期的注释 –

+0

还有'regmatches(string,gregexpr(paste(a,collapse =“|”),string))< - list(b)'将与'gsubfn'类似地工作 – thelatemail

2

中以及切削用少许功能只依赖于R base

repWords <- function(string,toRep,Rep,sep='\\s'){ 

    wrds <- unlist(strsplit(string,sep)) 
    ix <- match(toRep,wrds) 
    wrds[ix] <- Rep 
    return(paste0(wrds,collapse = ' ')) 

} 

a <- c("this", "is", "test") 
b <- c("that", "was", "boy") 

string <- "this is a story about a test" 

> repWords(string,a,b) 
[1] "that was a story about a boy" 

注:

这假定您有一个匹配的替换数量。您可以使用sep定义分隔符。

2

说到外部包,这里的另一个问题:

a <- c("this", "is", "test") 
b <- c("that", "was", "boy") 
x <- "this is a story about a test" 


library(qdap) 
mgsub(a,b,x) 

这给:

"that was a story about a boy" 
+0

不错的一个! 'mgsub'可以让生活变得更容易,看起来好像是 – Sotos

+0

如果'a < - “a”; b < - “A”'那么它会将'about'转换为'About',这看起来不正确。 –