问题
This question has been asked previously but hasn't been answered to the asker's satisfaction.
Given the following string:
mystring <- "one fish two fish red fish blue fish"
The following function allows to replace the nth occurrence of a word in it:
replacerFn <- function(String, word, rword, n){
stopifnot(n >0)
pat <- sprintf(paste0("^((.*?\\b", word, "\\b.*?){%d})\\b",
word,"\\b"), n-1)
rpat <- paste0("\\1", rword)
if(n >1) {
stringr::str_replace(String, pat, rpat)
} else {
stringr::str_replace(String, word, rword)
}
}
replacerFn(mystring, "fish", "dog", 1)
#[1] "one dog two fish red fish blue fish"
replacerFn(mystring, "fish", "dog", 2)
#[1] "one fish two dog red fish blue fish"
replacerFn(mystring, "fish", "dog", 3)
#[1] "one fish two fish red dog blue fish"
replacerFn(mystring, "fish", "dog", 4)
#[1] "one fish two fish red fish blue dog"
How do we have to adjust this function to replace the nth to last occurrence of the word?
2nd to last:
"one fish two dog red dog blue dog"
3rd to last:
"one fish two fish red dog blue dog"
and so on ...?
I tried things like str_replace_all or adjusting the regex part {1,} but without success.
Thanks for your help!
回答1:
Here is an easier option with gsubfn
library(gsubfn)
replacerFn2 <- function(String, word, rword, n) {
p <- proto(fun = function(this, x) if (count >= n) rword else x)
gsubfn(word, p, String)
}
replacerFn2(mystring, "fish", "dog", 2)
#[1] "one fish two dog red dog blue dog"
replacerFn2(mystring, "fish", "dog", 3)
#[1] "one fish two fish red dog blue dog"
replacerFn2(mystring, "fish", "dog", 4)
#[1] "one fish two fish red fish blue dog"
回答2:
Your function is rather complex, with conditions. An alternative approach is to split the string into a character vector of individual words, apply stringr
functions on it, then join it back into a single string:
library(stringr)
replace_function <- function(string, word, rword, n) {
vec <- unlist(strsplit(string, " "))
vec[str_which(vec, word)[n]] <- rword
str_c(vec, collapse = " ")
}
replace_function(mystring, "fish", "dog", 1)
[1] "one dog two fish red fish blue fish"
replace_function(mystring, "fish", "dog", 2)
[1] "one fish two dog red fish blue fish"
Now, you can modify this function very easily to replace the nth element from the end, using rev()
:
replace_end_function <- function(string, word, rword, n) {
vec <- unlist(strsplit(string, " "))
vec[rev(str_which(vec, word))[n]] <- rword
str_c(vec, collapse = " ")
}
replace_end_function(mystring, "fish", "dog", 1)
[1] "one fish two fish red fish blue dog"
replace_end_function(mystring, "fish", "dog", 2)
[1] "one fish two fish red dog blue fish"
Edit (my bad for thinking that "nth to last" meant "nth from last"):
To replace the nth to the last element:
replace_end_function <- function(string, word, rword, n) {
vec <- unlist(strsplit(string, " "))
vec[str_which(vec, word)[n:length(str_which(vec, word))]] <- rword
str_c(vec, collapse = " ")
}
replace_end_function(mystring, "fish", "dog", 1)
[1] "one dog two dog red dog blue dog"
replace_end_function(mystring, "fish", "dog", 2)
[1] "one fish two dog red dog blue dog"
replace_end_function(mystring, "fish", "dog", 3)
[1] "one fish two fish red dog blue dog"
replace_end_function(mystring, "fish", "dog", 4)
[1] "one fish two fish red fish blue dog"
回答3:
You can use grep
within your function replacerFn
, i.e.,
replacerFn <- function(String, word, rword, n) {
v <- unlist(strsplit(String,split = " "))
v[grep(word,v)[n:length(v)]] <- rword
return(paste0(v,collapse = " "))
}
来源:https://stackoverflow.com/questions/58859811/replace-from-nth-to-the-last-occurrence-of-word-in-string-text