2015-05-01 65 views
6

使用stringr包,很容易以矢量化的方式執行正則表達式替換。依次替換多個匹配具有不同替換的字符串中的單個模式的地方

問:我怎樣才能做到以下幾點:

hello,world??your,make|[]world,hello,pos 

更換每一個字不同的替代品,例如越來越多的數字

1,2??3,4|[]5,6,7 

請注意,簡單的分隔符不能被假設,實際使用情況更復雜。


stringr::str_replace_all似乎不工作,因爲它

str_replace_all(x, "(\\w+)", 1:7) 

產生向量應用到所有字,每個替換,它具有 不確定和/或重複的輸入項,以便

str_replace_all(x, c("hello" = "1", "world" = "2", ...)) 

將不能用於此目的。

+1

您可以使用'gsubfn'包。 – hwnd

回答

7

這是使用gsubfn的另一個想法。該pre功能的替代之前運行和fun功能運行每個取代:

library(gsubfn) 
x <- "hello,world??your,make|[]world,hello,pos" 
p <- proto(pre = function(t) t$v <- 0, # replace all matches by 0 
      fun = function(t, x) t$v <- v + 1) # increment 1 
gsubfn("\\w+", p, x) 

其中給出:

[1] "1,2??3,4|[]5,6,7" 

這種變化會因爲gsubfn維持使用的count變量給出相同的答案in proto functions:

pp <- proto(fun = function(...) count) 
gsubfn("\\w+", pp, x) 

查看gsubfn小插圖,瞭解使用的示例。

+2

非常好的答案。很高興看到你使用除'dplyr'以外的其他功能;) –

+0

你能解釋在替換部分使用的功能嗎? –

3

我建議"ore" package這樣的事情。特別值得注意的是ore.searchore.subst,後者可以接受函數作爲替換值。

實例:

library(ore) 

x <- "hello,world??your,make|[]world,hello,pos" 

## Match all and replace with the sequence in which they are found 
ore.subst("(\\w+)", function(i) seq_along(i), x, all = TRUE) 
# [1] "1,2??3,4|[]5,6,7" 

## Create a cool ore object with details about what was extracted 
ore.search("(\\w+)", x, all = TRUE) 
# match: hello world your make world hello pos 
# context:  ,  ?? , |[]  ,  , 
# number: 1==== 2==== 3=== 4=== 5==== 6==== 7== 
1

這裏,基礎R溶液。它也應該是矢量化的。

x="hello,world??your,make|[]world,hello,pos" 
#split x into single chars 
x_split=strsplit(x,"")[[1]] 
#find all char positions and replace them with "a" 
x_split[gregexpr("\\w", x)[[1]]]="a" 
#find all runs of "a" 
rle_res=rle(x_split) 
#replace run lengths by 1 
rle_res$lengths[rle_res$values=="a"]=1 
#replace run values by increasing number 
rle_res$values[rle_res$values=="a"]=1:sum(rle_res$values=="a") 
#use inverse.rle on the modified rle object and collapse string 
paste0(inverse.rle(rle_res),collapse="") 

#[1] "1,2??3,4|[]5,6,7" 
相關問題