1

Here's my code :

  V1 = list("1","2","3",c("1,2,3"))
  
  before =  c("1","2","3")
  after = c("2AB","1CD","DC2")
  
   stringi::stri_replace_all_regex(
    V1,
    before, 
    after, 
    vectorize_all = F)
  )
  

What I'm getting is :

>  stringi::stri_replace_all_regex(
+     V1,
+     before, 
+     after, 
+     vectorize_all = F)
[1] "1CDAB"         "1CD"           "DC2"           "1CDAB,1CD,DC2"

which is not what I'm trying to get which should look like this :

"2AB" "1CD" "DC2" "2AB,1CD,DC2"  

how do I solve this?

Mark
  • 7,785
  • 2
  • 14
  • 34
Akram H
  • 33
  • 4
  • Your regex is finding all instances of "1" and replacing them with "2AB", then replacing all "2"s with "1CD" including the "2"s just inserted by the first replacement. To amend this, look at setting a regex for a single digit with word breaks either side - from memory (so check) it might be `"\\b1\\b"` – Paul Stafford Allen Aug 24 '23 at 09:27

2 Answers2

2

Similar to Mr. Flick's answer to your previous question, but using str_split() to split values where necessary:

pacman::p_load(tidyverse)

# create a named list
d <- setNames(after, before)

# create function
f <- function(x) str_split(x, ",", simplify = TRUE) %>% {d[.]} %>% paste0(collapse = ",")

# apply function to all elements of V1
map_chr(V1, f)
# [1] "2AB"         "1CD"         "DC2"         "2AB,1CD,DC2"
Mark
  • 7,785
  • 2
  • 14
  • 34
2

You can try gsubfn like below

> library(gsubfn)

> relist(gsubfn("\\d+", setNames(as.list(after), before), unlist(V1)), V1)
[[1]]
[1] "2AB"

[[2]]
[1] "1CD"

[[3]]
[1] "DC2"

[[4]]
[1] "2AB,1CD,DC2"

If you would like to play with base R only, you can try

lapply(
    strsplit(unlist(V1), ""),
    \(x) paste0(c(",", after)[match(x, before, nomatch = 0) + 1], collapse = "")
)

which gives

[[1]]
[1] "2AB"

[[2]]
[1] "1CD"

[[3]]
[1] "DC2"

[[4]]
[1] "2AB,1CD,DC2"
ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81