Reputation: 10891
Is there an elegant way to take a vector like
x = c("a", "b", "c", "d", "e")
and make it be
x = c("b", "c", "d", "e", "a")
I did:
x = c("a", "b", "c", "d", "e")
firstVal = x[1]
x = tail(x,-1)
x[length(x)+1] = firstVal
x
[1] "b" "c" "d" "e" "a"
It works, but kinda ugly.
Upvotes: 6
Views: 5203
Reputation: 13046
Elegance is a matter of taste, and de gustibus non est disputandum:
> x <- c("a", "b", "c", "d", "e")
> c(x[-1], x[1])
[1] "b" "c" "d" "e" "a"
Upvotes: 13
Reputation: 491
The one thing that could potentially be improved with the previous answers is that you have to know the location number of the item you want to move, which in longer vectors could become an issue. You could instead do something like:
x <- c("a", "b", "c", "d", "e")
new_x <- c(x[-which(x == "a")], "a")
Upvotes: 2
Reputation: 109864
I had an idea to use both head
and tail
that turned out to be a flop when I benchmarked.
c(tail(x, -1), head(x, 1))
I figured I'd share the results as they're informative. I also scaled up for larger vectors and the results were interesting:
x <- c("a", "b", "c", "d", "e")
gagolews <- function() c(x[-1], x[1])
senoro <- function() x[c(2:length(x), 1)]
tyler <- function() c(tail(x, -1), head(x, 1))
ananda <- function() shifter(x, 1)
user <-function(){
firstVal = x[1]
x = tail(x,-1)
x[length(x)+1] = firstVal
x
}
library(microbenchmark)
(op <- microbenchmark(
gagolews(),
senoro(),
tyler(),
ananda(),
user(),
times=100L))
## Unit: microseconds
## expr min lq median uq max neval
## gagolews() 1.400 1.867 2.333 2.799 5.132 1000
## senoro() 1.400 1.867 2.333 2.334 10.730 1000
## tyler() 37.320 39.187 40.120 41.519 135.287 1000
## ananda() 39.653 41.519 42.452 43.386 69.043 1000
## user() 24.259 25.658 26.591 27.058 1757.789 1000
Here I scaled up. I only benched on 100 replications because of the size of the vector (1 million characters).
x <- rep(c("a", "b", "c", "d", "e"), 1000000)
## Unit: milliseconds
## expr min lq median uq max neval
## gagolews() 168.9151 171.3631 179.0490 193.9604 260.5963 100
## senoro() 192.2669 203.9596 259.1366 272.5570 341.4443 100
## tyler() 237.4218 246.5368 303.5700 319.3999 347.3610 100
## ananda() 237.9610 247.2097 303.9898 318.4564 342.2518 100
## user() 225.4503 234.3431 287.8348 300.8078 319.2051 100
Upvotes: 3
Reputation: 193517
Overkill time: You can consider my shifter
or my moveMe
function, both of which are part of my GitHub-only SOfun package.
Here are the relevant examples:
shifter
This is basically a head
and tail
approach:
## Specify how many values need to be shifted
shifter(x, 1)
# [1] "b" "c" "d" "e" "a"
shifter(x, 2)
# [1] "c" "d" "e" "a" "b"
## The direction can be changed too :-)
shifter(x, -1)
# [1] "e" "a" "b" "c" "d"
moveMe
This is fun:
moveMe(x, "a last")
# [1] "b" "c" "d" "e" "a"
## Lots of options to move things around :-)
moveMe(x, "a after d; c first")
# [1] "c" "b" "d" "a" "e"
Upvotes: 7
Reputation: 17412
Agreed with the matter of taste comment. My personal approach would be:
x[c(2:length(x), 1)]
Upvotes: 4