Insert a character at several positions in a string at once

Let's say I have a string

"ABCDEFGHI56dfsdfd"

      

What I want to do is insert a space in multiple positions at the same time.

For example, I want to insert a space at random by selecting two positions: 4 and 8.

So the output should be

"ABCD EFGH I56dfsdfd" 

      

What's the most efficient way to do this? Considering that a string can contain any types of characters (not just alphabets).

+3


source to share


3 answers


Here's a regex based solution:

vec <- "ABCDEFGHI56dfsdfd"

# sample two random positions
pos <- sample(nchar(vec), 2)
# [1] 6 4

# generate regex pattern
pat <- paste0("(?=.{", nchar(vec) - pos, "}$)", collapse = "|")
# [1] "(?=.{11}$)|(?=.{13}$)"

# insert spaces at (after) positions
gsub(pat, " ", vec, perl = TRUE)
# [1] "ABCD EF GHI56dfsdfd"

      



This approach is based on positive observations, for example (?=.{11}$)

. This example inserts a space up to 11 characters to the end of the line ( $

).

+6


source


A bit more brute force than Sven:



randomSpaces <- function(txt) {
  pos <- sort(sample(nchar(txt), 2))
  paste(substr(txt, 1, pos[1]), " ", 
        substr(txt, pos[1]+1, pos[2]), " ", 
        substr(txt, pos[2]+1, nchar(txt)), collapse="", sep="")  
}

for (i in 1:10) print(randomSpaces("ABCDEFGHI56dfsdfd"))

## [1] "ABCDEFG HI56 dfsdfd"
## [1] "ABC DEFGHI5 6dfsdfd"
## [1] "AB CDEFGHI56dfsd fd"
## [1] "ABCDEFGHI 5 6dfsdfd"
## [1] "ABCDEF GHI56dfsdf d"
## [1] "ABC DEFGHI56dfsdf d"
## [1] "ABCD EFGHI56dfsd fd"
## [1] "ABCDEFGHI56d fsdfd "
## [1] "AB CDEFGH I56dfsdfd"
## [1] "A BCDE FGHI56dfsdfd"

      

0


source


As per the accepted answer, here's a function to simplify this approach:

##insert pattern in string at position
substrins <- function(ins, x, ..., pos=NULL, offset=0){
    stopifnot(is.numeric(pos), 
              is.numeric(offset), 
              !is.null(pos))
    offset <- offset[1]
    pat <- paste0("(?=.{", nchar(x) - pos - (offset-1), "}$)", collapse = "|")
    gsub(pattern = pat, replacement = ins, x = x, ..., perl = TRUE)
}

# insert space at position 10
substrins(" ", "ABCDEFGHI56dfsdfd", pos = 10)
##[1] "ABCDEFGHI 56dfsdfd"

# insert pattern before position 10 (i.e. at position 9)
substrins(" ", "ABCDEFGHI56dfsdfd", pos = 10, offset=-1)
##[1] "ABCDEFGH I56dfsdfd"

# insert pattern after position 10 (i.e. at position 11)
substrins(" ", "ABCDEFGHI56dfsdfd", pos = 10, offset=1)
##[1] "ABCDEFGHI5 6dfsdfd"

      

Now, to do what the OP wanted:

# insert space at position 4 and 8
substrins(" ", "ABCDEFGHI56dfsdfd", pos = c(4,8))
##[1] "ABC DEFG HI56dfsdfd"

# insert space after position 4 and 8 (as per OP desired output)
substrins(" ", "ABCDEFGHI56dfsdfd", pos = c(4,8), offset=1)
##[1] "ABCD EFGH I56dfsdfd"

      

To reproduce a different, more crude-forceful answer, you would do:

set.seed(123)
x <- "ABCDEFGHI56dfsdfd"
for (i in 1:10) print(substrins(" ", x, pos = sample(nchar(x), 2)))
##[1] "ABCD EFGHI56d fsdfd"
##[1] "ABCDEF GHI56dfs dfd"
##[1] " ABCDEFGHI56dfsd fd"
##[1] "ABCDEFGH I56dfs dfd"
##[1] "ABCDEFG HI 56dfsdfd"
##[1] "ABCDEFG HI56dfsdf d"
##[1] "ABCDEFGHI 56 dfsdfd"
##[1] "A BCDEFGHI56dfs dfd"
##[1] " ABCD EFGHI56dfsdfd"
##[1] "ABCDE FGHI56dfsd fd"

      

0


source







All Articles