2

Given sample string:

tst_str <- c("abc", "123", "klm", "lop")

I would like to make the following replacements:

  • abc -> za12
  • 123 -> poi
  • klm -> uyt

Desired results

Simple nesting of gsub calls delivers the result:

gsub(
    pattern = "abc",
    replacement = "za12",
    x = gsub(
        pattern = "123",
        replacement = "poi",
        x = gsub(
            pattern = "klm",
            replacement = "uyt",
            x = tst_str
        )
    )
)
# [1] "za12" "poi"  "uyt"  "lop" 

Problem

I would like to arrive at identical results using purrr::map* or purrr::reduce functions. My initial take was to make use of purrr::reduce2

purrr::reduce2(
    .x = c("abc", "123", "klm"),
    .y = c("za12", "poi", "uyt"),
    .f = function(x, y, init) {
        gsub(pattern = x,
             replacement = y,
             x = init)
    },
    .init = tst_str
)

Clearly this is not the right way of doing that:

Warning message: In gsub(pattern = x, replacement = y, x = init) :
argument 'pattern' has length > 1 and only the first element will be used


Notes

Konrad
  • 17,740
  • 16
  • 106
  • 167
  • 1
    This might be useful reading. A totally uncool `for` loop (or `Reduce` variation if you *have* to use higher order functions) is pretty efficient and terse - https://stackoverflow.com/questions/26171318/regex-for-preserving-case-pattern-capitalization/26171700 – thelatemail May 28 '18 at 23:23
  • @thelatemail Thanks for that, it's good approach. Also the benchmarking results are useful. – Konrad May 29 '18 at 08:34

1 Answers1

7

You have the right idea, try reduce2 with stringr::str_replace():

library(purrr)
library(stringr)

tst_str <- c("abc", "123", "klm", "lop")
replacements <- c("za12", "poi", "uyt")
patterns <-  c("abc", "123", "klm")
reduce2(patterns, replacements, str_replace, .init=tst_str)

[1] "za12" "poi"  "uyt"  "lop" 

Note that .f in reduce2() just requires a function that takes 3 arguments. You don't actually have to explicitly pass them in, reduce will take care of that.

Alternately (although not higher-order):

names(replacements) <- patterns
str_replace_all(tst_str, replacements)
andrew_reece
  • 20,390
  • 3
  • 33
  • 58