How to reverse a string in R
Asked Answered
P

15

57

I'm trying to teach myself R and in doing some sample problems I came across the need to reverse a string.

Here's what I've tried so far but the paste operation doesn't seem to have any effect.

There must be something I'm not understanding about lists? (I also don't understand why I need the [[1]] after strsplit.)

test <- strsplit("greg", NULL)[[1]]
test
# [1] "g" "r" "e" "g"

test_rev <- rev(test)
test_rev
# [1] "g" "e" "r" "g"

paste(test_rev)
# [1] "g" "e" "r" "g"
Pistareen answered 28/11, 2012 at 19:33 Comment(8)
You're looking for paste(test_rev, collapse='').Woolridge
Thanks. Why is collapse required?Pistareen
That's the behavior of paste. Check out the documentation. If x and y are two string variables, paste(x,y) and paste(c(x, y)) give different results. You probably expected them to be the same.Woolridge
@mplourde The way I think about it that it allows for paste to behave in a vectorized manner like most other R functions.Schematic
@Schematic Yeah, thank goodness we don't have to write do.call(paste, as.list(my.atomic)).Woolridge
Seems that xkcd.com/1137 is appropriate here :-)Subirrigate
To better understand why you need the [[1]] after strsplit(), try running this: X <- strsplit(c("abc", "Statistics"), NULL); X; X[[1]]; X[[2]]Hawsepipe
Google says: r.789695.n4.nabble.com/reverse-string-td2288532.htmlSirocco
W
24

As @mplourde points out, you want the collapse argument:

paste(test_rev, collapse='')

Most commands in R are vectorized, but how exactly the command handles vectors depends on the command. paste will operate over multiple vectors, combining the ith element of each:

> paste(letters[1:5],letters[1:5])
[1] "a a" "b b" "c c" "d d" "e e"

collapse tells it to operate within a vector instead.

Warren answered 28/11, 2012 at 19:43 Comment(3)
So why would I write collapse=''? Wouldn't the '' evaluate to false? Shouldn't I be saying collapse=True? (Still learning my R basics)Pistareen
@Pistareen paste is a bit non-standard, and I think your intuition is perfectly R-like. However, in this case, ,collapse works like ,sep in that it specifies a character to insert in the final character vector. Try paste(test_rev, collapse='Whee!') for an illustration.Warren
@AriB.Friedman After collapsing it with paste, I get "c(\"l\", \"o\", \"o\", \"c\")". But the string was cool Whats wrong?Jackass
I
56

From ?strsplit, a function that'll reverse every string in a vector of strings:

## a useful function: rev() for strings
strReverse <- function(x)
        sapply(lapply(strsplit(x, NULL), rev), paste, collapse="")
strReverse(c("abc", "Statistics"))
# [1] "cba"        "scitsitatS"
Innuendo answered 28/11, 2012 at 19:46 Comment(1)
Nice, same function rewritten the dplyr/magrittr way for readability strreverse <- function(x){ strsplit(x, NULL) %>% lapply(rev) %>% sapply(paste, collapse="") }.Lupulin
R
42

stringi has had this function for quite a long time:

stringi::stri_reverse("abcdef")
## [1] "fedcba"

Also note that it's vectorized:

stringi::stri_reverse(c("a", "ab", "abc"))
## [1] "a"   "ba"  "cba"
Roundabout answered 14/6, 2016 at 14:9 Comment(1)
This reverses characters, not strings.Newmint
W
24

As @mplourde points out, you want the collapse argument:

paste(test_rev, collapse='')

Most commands in R are vectorized, but how exactly the command handles vectors depends on the command. paste will operate over multiple vectors, combining the ith element of each:

> paste(letters[1:5],letters[1:5])
[1] "a a" "b b" "c c" "d d" "e e"

collapse tells it to operate within a vector instead.

Warren answered 28/11, 2012 at 19:43 Comment(3)
So why would I write collapse=''? Wouldn't the '' evaluate to false? Shouldn't I be saying collapse=True? (Still learning my R basics)Pistareen
@Pistareen paste is a bit non-standard, and I think your intuition is perfectly R-like. However, in this case, ,collapse works like ,sep in that it specifies a character to insert in the final character vector. Try paste(test_rev, collapse='Whee!') for an illustration.Warren
@AriB.Friedman After collapsing it with paste, I get "c(\"l\", \"o\", \"o\", \"c\")". But the string was cool Whats wrong?Jackass
S
12

The following can be a useful way to reverse a vector of strings x, and is slightly faster (and more memory efficient) because it avoids generating a list (as in using strsplit):

x <- rep( paste( collapse="", LETTERS ), 100 )
str_rev <- function(x) {
  sapply( x, function(xx) { 
    intToUtf8( rev( utf8ToInt( xx ) ) )
  } )
}
str_rev(x)

If you know that you're going to be working with ASCII characters and speed matters, there is a fast C implementation for reversing a vector of strings built into Kmisc:

install.packages("Kmisc")
str_rev(x)
Stranger answered 25/12, 2012 at 8:31 Comment(1)
even faster would be str_rev <- function(x) intToUtf8(rev(utf8ToInt(x))) and to vectorize it (what your sapply does), do str_rev <- Vectorize(str_rev) (but it uses mapply under the hood). Are you sure, that sapply does not create a list as a intermediate product? Definitely, it is faster than strsplit. Nice trick with utf8ToInt and intToUtf8 - thank you! and rev.Turnstone
O
11

You can also use the IRanges package.

library(IRanges)
x <- "ATGCSDS"
reverse(x)
# [1] "SDSCGTA"

You can also use the Biostrings package.

library(Biostrings)
x <- "ATGCSDS"
reverse(x)
# [1] "SDSCGTA"
Orography answered 26/2, 2014 at 12:14 Comment(0)
A
8

If your data is in a data.frame, you can use sqldf:

myStrings <- data.frame(forward = c("does", "this", "actually", "work"))
library(sqldf)
sqldf("select forward, reverse(forward) `reverse` from myStrings")
#    forward  reverse
# 1     does     seod
# 2     this     siht
# 3 actually yllautca
# 4     work     krow
Ariew answered 29/11, 2012 at 8:38 Comment(0)
A
5

Here is a function that returns the whole reversed string, or optionally the reverse string keeping only the elements specified by index, counting backward from the last character.

revString = function(string, index = 1:nchar(string)){
  paste(rev(unlist(strsplit(string, NULL)))[index], collapse = "")
}

First, define an easily recognizable string as an example:

(myString <- paste(letters, collapse = ""))

[1] "abcdefghijklmnopqrstuvwxyz"

Now try out the function revString with and without the index:

revString(myString)

[1] "zyxwvutsrqponmlkjihgfedcba"

revString(myString, 1:5)

[1] "zyxwv"

Alvey answered 29/6, 2015 at 23:14 Comment(0)
A
5

The easiest way to reverse string:

#reverse string----------------------------------------------------------------
revString <- function(text){
  paste(rev(unlist(strsplit(text,NULL))),collapse="")
}

#example:
revString("abcdef")
Adolpho answered 17/2, 2017 at 9:54 Comment(0)
A
5

You can do with rev() function as mentioned in a previous post.

`X <- "MyString"

RevX <- paste(rev(unlist(strsplit(X,NULL))),collapse="")

Output : "gnirtSyM"

Thanks,

Antoninaantonino answered 26/3, 2018 at 9:5 Comment(2)
There is no point in answering 5 year old questions, with 25000 views already. Your answer will be buried somewhere no one will see. Instead answer the latest questionsBradwell
Nothing wrong with answering old questions. I can see his answer just fine.Hubbub
S
3

The following Code will take input from user and reverse the entire string-

revstring=function(s)
print(paste(rev(strsplit(s,"")[[1]]),collapse=""))

str=readline("Enter the string:")
revstring(str)
Subordinary answered 16/10, 2017 at 15:14 Comment(0)
C
2

Here's a solution with gsub. Although I agree that it's easier with strsplit and paste (as pointed out in the other answers), it may be interesting to see that it works with regular expressions too:

test <- "greg"

n <- nchar(test) # the number of characters in the string

gsub(paste(rep("(.)", n), collapse = ""),
     paste("", seq(n, 1), sep = "\\", collapse = ""),
     test)

# [1] "gerg"
Chloral answered 29/11, 2012 at 7:26 Comment(1)
@mvkorpel This is true. It is more a demonstration of the concept, not a general solution.Chloral
U
2
##function to reverse the given word or sentence

reverse <- function(mystring){ 
n <- nchar(mystring)
revstring <- rep(NA, n)
b <- n:1
c <- rev(b)
for (i in 1:n) {
revstring[i] <- substr(mystring,c[(n+1)- i], b[i])
 }
newrevstring <- paste(revstring, sep = "", collapse = "")
return (cat("your string =", mystring, "\n",
("reverse letters = "), revstring, "\n", 
"reverse string =", newrevstring,"\n"))
}
Ulent answered 6/5, 2015 at 4:41 Comment(0)
S
2

Here is one more base-R solution:

# Define function
strrev <- function(x) {
  nc <- nchar(x)
  paste(substring(x, nc:1, nc:1), collapse = "")
}

# Example
strrev("Sore was I ere I saw Eros")
[1] "sorE was I ere I saw eroS"

Solution was inspired by these U. Auckland slides.

Salmon answered 9/7, 2017 at 22:13 Comment(0)
E
1

So apparently front-end JS developers get asked to do this (for interviews) in JS without using built-in reverse functions. It took me a few minutes, but I came up with:

string <- 'hello'

foo <- vector()

for (i in nchar(string):1) foo <- append(foo,unlist(strsplit(string,''))[i])
paste0(foo,collapse='')

Which all could be wrapped in a function...

What about higher-order functionals? Reduce?

Enidenigma answered 18/2, 2018 at 1:53 Comment(1)
Much more efficient to use rev or a library's string function.Underclay
B
1

Might be not as efficient as other answers here, but substr - as opposed to substring (see this answer) - can be forced into string reversing either by using a vector of repeated values or a Map function:

S="olYUH nitup"

paste0(substr(rep(S, n<-nchar(S)), n:1, n:1), collapse="")
>[1] "putin HUYlo"

Reduce(paste0, Map(\(j)substr(S, j, j), nchar(S):1))
>[1] "putin HUYlo"
Blackman answered 9/5 at 10:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.