Replace multiple characters, by index, in a string quickly

核能气质少年 提交于 2020-06-09 03:00:11

问题


I'm trying to quickly replace multiple characters in a string with another character such as *

For example, I have a string such as:

string = "abcdefghij"

I also have a vector of indexes that indicate where I would like to replace letters in the above string with another character.

string_indexes_replaced = c(1, 4, 6, 9)

Desired output:

"*bc*e*gh*j"

What I've done

I've tried a very novice like approach of splitting the characters up into a list, replacing the characters with *, then collapsing the list back into the desired string, as shown below:

library(dplyr)
library(stringi)

string%>%
strsplit(split = "")%>%
lapply(function(x) replace(x, string_indexes_replaced, rep("*", length(string_indexes_replaced))))%>%
lapply(stri_flatten)%>%
unlist(use.names = FALSE)

which outputs

"*bc*e*gh*j"

but it is clear that there should be something simpler and faster than what I've posted above. Is there anything simpler & quicker than what I've demonstrated here?


回答1:


in base R, besides the method of substring() and for-loop shown by @akrun,, you can use utf8ToInt() and intToUtf8 to make it

v <- utf8ToInt(string)
v[string_indexes_replaced ] <- utf8ToInt("*")
res <- intToUtf8(v)

which gives

> res
[1] "*bc*e*gh*j"



回答2:


We can use substring

v1 <- c(1, 4, 6, 9)
for(i in seq_along(v1)) substring(string, v1[i], v1[i]) <- "*"
#[1] "*bc*e*gh*j"

As we are using stringi, another option is

library(stringi)
stri_sub_all(string, from = v1, length = 1) <- "*"
string
#[1] "*bc*e*gh*j"



回答3:


A simple recursive solution. The time efficiency should be same as iteration (for loop). The benefit is there is no side-effect (assignment of integer ks is localized), so that we can treat its whole computation as a functional abstract and feed it to other part of the bigger program which we are working on. It will help to modularize the code.

# multi-replace for character vector input with length greater than 1
multi_replace_v <- function(v, r, ks) {
  ks <- as.integer(ks)
  if (length(ks) == 0) {
    v
  } else if (length(ks) == 1) {
    if (ks[[1]] > length(v) | ks[[1]] < 1) {
      stop("Invalid parameter: ks=", as.character(ks[[1]]), ". Valid range: 1-", as.character(length(v)))
    } else if (ks[[1]] == 1) {
      c(r, v[-1])
    } else if (ks[[1]] == length(v)) {
      c(v[-length(v)], r)
    } else {
      c(v[1:(ks[[1]]-1)], r, v[(ks[[1]]+1):length(v)])
      }
  } else {
    multi_replace_v(multi_replace_v(v, r, ks[[1]]), r, ks[-1])
  }
}

# multi-replace for input of single string character vector
multi_replace_s <- function(s, r, ks) paste0(multi_replace_v(unlist(strsplit(s, '')), r, ks), collapse = '') 

# multi-replace for both single string and long vector input
multi_replace <- function(v_or_s, r, ks) {
  if (length(v_or_s) == 1) {
    multi_replace_s(v_or_s, r, ks)
  } else if (length(v_or_s) > 1) {
    multi_replace_v(v_or_s, r, ks)
  } else {
    NULL
  }
}

# Example
> multi_replace('abcdefghij', "*", c(1,4,6,9))
[1] "*bc*e*gh*j"


来源:https://stackoverflow.com/questions/59095245/replace-multiple-characters-by-index-in-a-string-quickly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!