user3664020
user3664020

Reputation: 3020

Insert a character at multiple positions in a string at once

Let us say I have a string

"ABCDEFGHI56dfsdfd"

What I want to do is insert a space character at multiple positions at once.

For eg. I want to insert space character at randomly chosen two positions say 4 and 8.

So the output should be

"ABCD EFGH I56dfsdfd" 

What is the most effective way of doing this? Given the string can have any type of characters in it (not just the alphabets).

Upvotes: 3

Views: 1323

Answers (3)

landroni
landroni

Reputation: 2988

Based on the accepted answer, here's a function that simplifies 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's desired output)
substrins(" ", "ABCDEFGHI56dfsdfd", pos = c(4,8), offset=1)
##[1] "ABCD EFGH I56dfsdfd"

To replicate the other, more brute-force-y answer one 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"

Upvotes: 0

Sven Hohenstein
Sven Hohenstein

Reputation: 81713

Here's a solution based on regular expressions:

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 lookaheads, e.g., (?=.{11}$). In this example, a space is inserted at 11 characters before the end of the string ($).

Upvotes: 6

hrbrmstr
hrbrmstr

Reputation: 78832

A bit more brute-force-y than Sven's:

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"

Upvotes: 0

Related Questions