84

Suppose I have a vector v, how do I get its reverse, i.e. last element first?

The first thing that comes to me is v[length(v):1], but it returns NA when v is numeric(0), while user normally expect sorting nothing returns nothing, not sorting nothing returns the unavailable thing - it does make a big difference in my case.

smci
  • 32,567
  • 20
  • 113
  • 146
Tankman六四
  • 1,638
  • 2
  • 13
  • 19

2 Answers2

127

You are almost there; rev does what you need:

rev(1:3)
# [1] 3 2 1
rev(numeric(0))
# numeric(0)

Here's why:

rev.default
# function (x) 
# if (length(x)) x[length(x):1L] else x
# <bytecode: 0x0b5c6184>
# <environment: namespace:base>

In the case of numeric(0), length(x) returns 0. As if requires a logical condition, it coerces length(x) to TRUE or FALSE. It happens that as.logical(x) is FALSE when x is 0 and TRUE for any other number.

Thus, if (length(x)) tests precisely what you want - whether x is of length zero. If it isn't, length(x):1L has a desirable effect, and otherwise there is no need to reverse anything, as @floder has explained in the comment.

Julius Vainora
  • 47,421
  • 9
  • 90
  • 102
  • 6
    +1 - just to explain what is happening with the OP in the case where `v <- c()`: `length(v):1` is `0:1`. The `[` operator ignores the `0` and returns `v[1]`, i.e. `NA`. If it were not for `rev`, something robust and along the lines of the OP would have been `v[seq(to = 1, by = -1, length.out = length(v))]`. – flodel Sep 21 '13 at 15:59
0

Re: flodel's comment, if you want to try recreating rev() yourself, you could do something like:

rev2 <- function(v) if (length(v) > 0) v[length(v):1] else v

And in fact, this is actually what rev() is - see the source code here.

Mark
  • 7,785
  • 2
  • 14
  • 34