Replace 'from nth to the last' occurrence of word in string/text

大城市里の小女人 提交于 2019-12-13 14:42:19

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!