29

Suppose I have a long string:

"XOVEWVJIEWNIGOIWENVOIWEWVWEW"

How do I split this to get every 5 characters followed by a space?

"XOVEW VJIEW NIGOI WENVO IWEWV WEW"

Note that the last one is shorter.

I can do a loop where I constantly count and build a new string character by character but surely there must be something better no?

Ben Bolker
  • 173,430
  • 21
  • 312
  • 389
user1357015
  • 9,314
  • 16
  • 56
  • 100
  • 4
    check out this question: https://stackoverflow.com/questions/2247045/chopping-a-string-into-a-vector-of-fixed-width-character-elements – n8sty Oct 21 '14 at 22:48
  • Does this answer your question? [Chopping a string into a vector of fixed width character elements](https://stackoverflow.com/questions/2247045/chopping-a-string-into-a-vector-of-fixed-width-character-elements) – tjebo Jan 23 '21 at 16:54

5 Answers5

58

Using regular expressions:

gsub("(.{5})", "\\1 ", "XOVEWVJIEWNIGOIWENVOIWEWVWEW")
# [1] "XOVEW VJIEW NIGOI WENVO IWEWV WEW"
flodel
  • 82,429
  • 18
  • 167
  • 205
  • 1
    @flodel, can you help explain "\\1 "? I've figured everything else out but that stumbles me – user1357015 Oct 22 '14 at 03:38
  • 1
    @user1357015 I think hwnd does a nice job explaining this idea here: http://stackoverflow.com/a/26495062/1000343 – Tyler Rinker Oct 22 '14 at 03:44
  • this is awesome, and super fast :) – Brian D Jun 20 '18 at 13:27
  • What would be the way to reverse this? For example, how would you do this starting from the right, and going to left? Also, instead of splitting by 5, lets say i want the first 8 characters and the last 6 characters separated, so it would look like: ` "XOVEWVJI EWNIGOIWENVOIW EWVWEW" ` – Lasarus9 May 28 '19 at 17:26
14

Using sapply

> string <- "XOVEWVJIEWNIGOIWENVOIWEWVWEW"
> sapply(seq(from=1, to=nchar(string), by=5), function(i) substr(string, i, i+4))
[1] "XOVEW" "VJIEW" "NIGOI" "WENVO" "IWEWV" "WEW"  
Jilber Urbina
  • 50,760
  • 8
  • 101
  • 127
9

You can try something like the following:

s <- "XOVEWVJIEWNIGOIWENVOIWEWVWEW" # Original string
l <- seq(from=5, to=nchar(s), by=5) # Calculate the location where to chop

# Add sentinels 0 (beginning of string) and nchar(s) (end of string)
# and take substrings. (Thanks to @flodel for the condense expression)
mapply(substr, list(s), c(0, l) + 1, c(l, nchar(s))) 

Output:

[1] "XOVEW" "VJIEW" "NIGOI" "WENVO" "IWEWV" "WEW"

Now you can paste the resulting vector (with collapse=' ') to obtain a single string with spaces.

musically_ut
  • 33,232
  • 8
  • 87
  • 102
8

No *apply stringi solution:

x <- "XOVEWVJIEWNIGOIWENVOIWEWVWEW"
stri_sub(x, seq(1, stri_length(x),by=5), length=5)
[1] "XOVEW" "VJIEW" "NIGOI" "WENVO" "IWEWV" "WEW" 

This extracts substrings just like in @Jilber answer, but stri_sub function is vectorized se we don't need to use *apply here.

bartektartanus
  • 12,415
  • 4
  • 70
  • 92
6

You can also use a sub-string without a loop. substring is the vectorized substr

x <- "XOVEWVJIEWNIGOIWENVOIWEWVWEW"
n <- seq(1, nc <- nchar(x), by = 5) 
paste(substring(x, n, c(n[-1]-1, nc)), collapse = " ")
# [1] "XOVEW VJIEW NIGOI WENVO IWEWV WEW"
Rich Scriven
  • 90,041
  • 10
  • 148
  • 213