I wanted to combine R's rev() function and strsplit function to check if a string is a palindrome. My idea was to use strsplit() to split up my character string into individual letters and then use rev on the result to reverse the order of the letters. So, say:
a = "summer"
and we do:
b = strsplit(a,"")
We get:
[[1]]
[1] "s" "u" "m" "m" "e" "r"
Looks like it should work. But use rev on this:
rev(b)
and the output doesn't change:
[[1]]
[1] "s" "u" "m" "m" "e" "r"
Now, I've narrowed down the answer to have something to do with the '[[1]]', which I recognise as list notation. If we do:
c = strsplit(a,"")[[1]]
We get:
[1] "s" "u" "m" "m" "e" "r"
i.e. no '[[1]]'. Now, if we use rev(c) here, we get the desired result:
[1] "r" "e" "m" "m" "u" "s"
Similarly, if we have:
d = 1:10
and use rev(d), we get:
[1] 10 9 8 7 6 5 4 3 2 1
What both of the successful attempts have in common is the lack of list notation. Could anybody enlighten me as to how R is treating our initial character string and why using list notation with strsplit allows us to utlise rev properly?
CodePudding user response:
What is happening here is that when you call rev(b)
, you are reversing a list which has just one element in it. That one element is a vector of characters. So the reverse operation just returns the same thing:
b <- strsplit(a, "")
rev(b)
[[1]]
[1] "s" "u" "m" "m" "e" "r"
However, when you access the first (and only) element of that list, you reverse the vector of letters:
rev(b[[1]])
[1] "r" "e" "m" "m" "u" "s"
If you take a list with more than one element and reverse it, you will see the elements reverse:
lst <- list(a=c("v", "x"), b=c("y", "z"))
lst
$a
[1] "v" "x"
$b
[1] "y" "z"
rev(lst)
$b
[1] "y" "z"
$a
[1] "v" "x"