Replacing multiple patterns via str_replace

Hi,
I would like to identify multiple patterns in a character vector and replace each pattern with a specific replacement.
For this, I extract each match, modify the letters in the way I need and would like to replace the old matches with the modified ones in the original vector.

words <- c( "apple", "banana", "coconut", "froppyland")

extraction <- str_extract_all(words, "[aeiou]")
workcases <- unlist(extraction)
workcases <- str_c(workcases, "x", workcases)

str_replace_all(words, "[aeiou]", workcases)

Here, I extract all cases where a vowel appears in the vector, I create a replacement vector so that each vowel is transformed into "vowel-x-vowel" and then I would like to replace each match in the words-vector with the transformed cases.
The problem is I get this output:

[1] "axapplaxa" "bexenexenexe" "caxacaxanaxat" "fraxapylaxand" "axapplaxa" "boxonoxonoxo" "coxocoxonoxot" "fruxupyluxund" "oxopploxo"
[10] "baxanaxanaxa"
Warning message:
In stri_replace_all_regex(string, pattern, fix_replacement(replacement), :
longer object length is not a multiple of shorter object length

... which means that the str_replace_all function does not apply each element of the replacement vector to the appropriate pattern match, even though the amount of matches and the lenghth of the replacement vector are identical.

Can someone tell me how I can replace a number of matches with an equal number of replacements?

Thanks in advance

I think this is a good approach :

library(tidyverse)

# function that can replace any single vowel from a word with vowel-x-vowel
rvwl <- function(word,x){
str_replace_all(word,
                pattern=x,
                replacement=str_c(x,"x",x))
}

# function that replaces specific vowels using the above
replace_vowels <- function(word){
  word %>%
  rvwl("a") %>%
    rvwl("e") %>%
    rvwl("i") %>%
    rvwl("o") %>%
    rvwl("u") 
}

(words <- c( "apple", "banana", "coconut", "froppyland"))

map(words,replace_vowels)
1 Like
library(tidyverse)

words <- c( "apple", "banana", "coconut", "froppyland")
str <- list()
str$pattern <- c("a", "e", "i", "o", "u")
str$replacement <- rep("x", length(str$pattern))

# one line of code with reduce!
reduce(transpose(str), ~str_replace(.x, .y$pattern, .y$replacement), .init = words)
#> [1] "xpplx"      "bxnana"     "cxconxt"    "frxppylxnd"

Created on 2021-08-02 by the reprex package (v1.0.0)

Actually this is an even more elegant solution using reduce2.

  library(tidyverse)

words <- c( "apple", "banana", "coconut", "froppyland")
str <- list()
str$pattern <- c("a", "e", "i", "o", "u")
str$replacement <- rep("x", length(str$pattern))

reduce2(str$pattern, str$replacement, str_replace, .init = words)
#> [1] "xpplx"      "bxnana"     "cxconxt"    "frxppylxnd"

Created on 2021-08-02 by the reprex package (v1.0.0)

thx, this seems to work in this case. But this does not work with regular expressions in the replace_vowels function does it? because i would also like to match for more complicated things such as a OR b OR c or a letter followed by a specific other letter.

replace a or e or i or u or b or c ...

library(tidyverse)

(words <- c( "apple", "banana", "coconut", "froppyland"))
map(words,~str_replace_all(.x,
                           pattern="([aeioubc])",
                           replacement=str_c("\\1","x","\\1")))

Cool, thats works well. Thank you!

If I may ask you one more thing:

The rules for the argument of str_replace_all() are not fully clear to me. Because if I wanted to do the exact inverse, I would do it like the following:
(words <- c( "axapplexe", "baxanaxanaxa", "coxocoxonuxut", "froxoppylaxand"))
map(words,~str_replace_all(.x,
pattern="([aeiou]x[aeiou])",
replacement=unlist(str_split("\\1", "x"))[1])

so i want to split the match at a certain letter and use the part before the match as replacement. But this doesnt seem to work. Do you have a tip here?

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.