3

Given a string with different placeholders I want to replace, does R have a function that replace all of them given a vector of patterns and a vector of replacements?

I have managed to accomplish that with a list and a loop

> library(stringr)    
> tt_ori <- 'I have [%VAR1%] and [%VAR2%]'
> tt_out <- tt_ori

> ttlist <- list('\\[%VAR1%\\]'="val-1", '\\[%VAR2%\\]'="val-2")
> ttlist
$`\\[%VAR1%\\]`
[1] "val-1"

$`\\[%VAR2%\\]`
[1] "val-2"

> for(var in names(ttlist)) {
+ print(paste0(var," -> ",ttlist[[var]]))
+ tt_out <- stringr::str_replace_all(string = tt_out, pattern =var, replacement = ttlist[[var]] )
+ }
[1] "\\[%VAR1%\\] -> val-1"
[1] "\\[%VAR2%\\] -> val-2"
> tt_out
[1] "I have val-1 and val-2"

There is a similar question R: gsub, pattern = vector and replacement = vector but it is asking for replacing different strings each one with only one of the patterns. Here I am looking for replacing all the patterns in a single string.

I have tried

> tt_ori <- 'I have VAR1 and VAR2'
> tt_out <- tt_ori
> ttdf <- data.frame(tt=c("VAR1", "VAR2"), val=c("val-1", "val-2"), stringsAsFactors = F)
> str(ttdf)
'data.frame':   2 obs. of  2 variables:
 $ tt : chr  "VAR1" "VAR2"
 $ val: chr  "val-1" "val-2"
> stringr::str_replace_all(string = tt_out, pattern =ttdf$tt, replacement = ttdf$val )
[1] "I have val-1 and VAR2" "I have VAR1 and val-2"

Obviously the output is not what I want (several output strings, every one with only one substitution).

I was wondering if a function exist in base or in a well known CRAN package that would be called like the one shown before and would be capable of doing all substitutions in a single string.

Do someone have a better solution or recomendation for my loop or should I convert it into a function?.

[Note] the strings could be small webpage templates, o configuration files. they are small so making a loop for 10 or 20 substitutions is not a big deal but I am looking for more elegant solutions.

Community
  • 1
  • 1
Pablo Marin-Garcia
  • 4,151
  • 2
  • 32
  • 50
  • If your expected output is `tt_out` based on the input `tt_ori`, `mgsub` should work `mgsub(c('[%VAR1%]' , '[%VAR2%]'), c('val-1', 'val-2'), tt_ori)` – akrun Feb 15 '15 at 19:01
  • @akrun Where you talking about the mgsub in qdap? http://www.inside-r.org/packages/cran/qdap/docs/multigsub. Looking for it I have just found this link http://stackoverflow.com/questions/15253954/replace-multiple-arguments-with-gsub where some mgsub functions are implemented. If you write the comment as answer I would accept it – Pablo Marin-Garcia Feb 15 '15 at 19:18
  • @akrun, The @ in your previous comment points to other Pablo ;-) – Pablo Marin-Garcia Feb 15 '15 at 22:00

2 Answers2

1

Try

library(qdap)
 mgsub(c('[%VAR1%]' , '[%VAR2%]'), c('val-1', 'val-2'), tt_ori)
#[1] "I have val-1 and val-2"

data

 tt_ori <- 'I have [%VAR1%] and [%VAR2%]'
akrun
  • 874,273
  • 37
  • 540
  • 662
  • I did not try before mgsub because I did not have installed qdap. I saw the function in this comment http://stackoverflow.com/questions/19424709/r-gsub-pattern-vector-and-replacement-vector#comment43458372_19426663 but they said it has a lot of dependencies and in the answer http://stackoverflow.com/a/19426663/427129 they make equivalent the mgsub command to `names(x1) <- mapply(gsub, a, b, names(x1))` that does not give the result as I want it. – Pablo Marin-Garcia Feb 15 '15 at 21:52
  • Thanks I have intalled qdap and all its dependencies `> install.packages('qdap') also installing the dependencies ‘data.table’, ‘assertthat’, ‘magrittr’, ‘lazyeval’, ‘openNLPdata’, ‘qdapDictionaries’, ‘qdapRegex’, ‘qdapTools’, ‘dplyr’, ‘gender’, ‘gridExtra’, ‘igraph’, ‘NLP’, ‘openNLP’, ‘reports’, ‘stringdist’, ‘tm’, ‘venneuler’` and your answer is correct. – Pablo Marin-Garcia Feb 15 '15 at 21:58
  • A final note: it is worthy to note that mgsub does not need to escape square brackets in the pattern section as gsub needs. On the other hand this mean it can not accept regex patterns. I have made anew question about how can I pass a regular expression to mgsub. http://stackoverflow.com/questions/28532172/r-qdapmgsub-how-to-pass-a-pattern-with-a-regular-expression – Pablo Marin-Garcia Feb 15 '15 at 22:52
  • 1
    @PabloMarin-Garcia Thanks for the comments. Yes, it have a lot of dependencies. Your new question already got the answer:-) – akrun Feb 16 '15 at 03:32
  • Looking at the source, I noticed `mgsub` is a for loop around `gsub`. – Karsten W. Feb 17 '21 at 18:10
0

This seems to achieve what you need.

tt_ori <- 'I have [%VAR1%] and [%VAR2%]'
patterns <- c('\\[%VAR1%\\]', '\\[%VAR2%\\]')
replacements <- c("val-1", "val-2")

stringr::str_replace_all(tt_ori, set_names(replacements, patterns))
# [1] "I have val-1 and val-2"
Jakub.Novotny
  • 2,912
  • 2
  • 6
  • 21
  • Doesn't work if patterns and replacements are mismatched sizes - i.e. trying to replace all in `patterns` above with nothing `""` – Ndharwood May 03 '23 at 16:39
  • 1
    @Ndharwood for replacing multiple patterns with nothing, you may want to use `str_remove_all`. Something like `str_remove_all(tt_ori, paste(patterns, collapse = "|"))`. – Jakub.Novotny May 06 '23 at 08:00