How to use map with str_replace_all for multiple pattern replacements

Viewed 274

I have a string and would like to capitalize two lowercase words. The following accomplishes what I want:

library(tidyverse)

"this is a test" %>% 
  str_replace_all("this", toupper("this")) %>% 
  str_replace_all("test", toupper("test"))

However, I would like to do this in a more efficient way as I have a lot of patterns to replace and do not want a separate line per pattern. I thought about using map, however I cannot get it to execute properly as the code below throws an error:

"this is a test" %>% 
  c("this", "test") %>% 
  map_chr(~str_replace_all(.x, toupper(.x)))

Can anyone tell me how to accomplish this?

4 Answers

In regex, you can use \\U to change the capture group to upper case. Use | to separate different patterns.

val <- c("this", "test")
string <- "this is a test"

gsub(sprintf('(%s)', paste0(val, collapse = '|')), '\\U\\1', string, perl = TRUE)
#[1] "THIS is a TEST"

To answer your question you can use for loop to achieve the result that you are looking for.

for(i in val) {
  string <- stringr::str_replace_all(string, i, toupper(i))   
}

map/lapply does not have "knowledge" about the changes which happen in the middle hence it works on the same input.

In tidyverse, we may use reduce to do this

library(stringr)
library(purrr)
reduce(val, ~ str_replace_all(.x, .y, toupper(.y)), .init = string)
[1] "THIS is a TEST"

data

val <- c("this", "test")
string <- "this is a test"

Here's an alternative method packaged up into a function.

> SomeToUpper <- function(string_all, word_vector){
+   return(paste(
+     sapply(
+       unlist(str_split(string_all, " ")),
+       function(word){ 
+         ifelse(
+           word %in% word_vector, 
+           str_to_upper(word), 
+           word)}),
+     collapse = " ")
+   )
+ }
> SomeToUpper("this is a test", c("this", "test"))
[1] "THIS is a TEST"

Another recursion method using Reduce + gsub

> Reduce(
+   function(x, p) gsub(paste0("(", p, ")"), "\\U\\1", x, perl = TRUE),
+   val,
+   string
+ )
[1] "THIS is a TEST"
Related