how to replace all but one character in a set of identifcal strings (different character stays not replaced in each string)?

Viewed 110

I have a character vector of identical elements:

vec <- c("AXAXAXA", "AXAXAXA", "AXAXAXA")

I would like to replace "X" with "Y" but leave one "X" behind in each string, different one in each string, so I get

vec_res <- c("AXAYAYA", "AYAXAYA", "AYAYAXA")

The strings are always the same and the number of elements (strings) in the vector is the same as the number of "X" in each string

I am new to sringr but I suspect there could be a smart way to do this.

3 Answers

One option utilizing purrr could be:

map2_chr(.x = grepRaw("X", vec[1], all = TRUE),
         .y = vec,
         ~ `substr<-`(gsub("X", "Y", .y), .x, .x, "X"))

[1] "AXAYAYA" "AYAXAYA" "AYAYAXA"

The same thing with base R:

mapply(function(x, y) `substr<-`(gsub("X", "Y", y), x, x, "X"),
       x = grepRaw("X", vec[1], all = TRUE),
       y = vec)

I'm not sure this is a very common operator or that stringr will help much here. Here's a base R function. Since the repetition of the input vector is redundant, this function expects a single value and will generate an output value for each of the X's

swap_expand <- function(x) {
  stopifnot(length(x)==1)
  m <- gregexpr("X", x)
  regmatches(x, m) <- "Y"  #set all X's to Y
  m <- m[[1]]
  r <- rep(x, length(m))   #repeat for each X
  substr(r, m, m)<-"X"     #replace a different Y each time
  r
}

swap_expand("AXAXAXA")
# [1] "AXAYAYA" "AYAXAYA" "AYAYAXA"

Another one

x <- 'AXAXAXA'
y <- grepRaw('X', x, all = TRUE)
x <- chartr('X', 'Y', rep(x, length(y)))
substr(x, y, y + 1) <- 'X'
x
# [1] "AXAYAYA" "AYAXAYA" "AYAYAXA"
Related