John-Henry
John-Henry

Reputation: 1817

How to keep indexing within the bounds of a vector?

How can index a vector circularly?

I have a vector of numbers. I would like to index this vector one a time (e.g., i[1], i[2] ...). However after the index_n > length(i) I would like the index to "circle" back through the vector again again.

i = c("cat", "dog", "ghost")
i[4] # 4 is 1 greater than than the length of the vector, i want to return the first element "cat"
## > NA

There are a lot of ways I could do this with a logical statements. I am wondering if there is a function that does this already.

Upvotes: 1

Views: 44

Answers (1)

MrFlick
MrFlick

Reputation: 206606

There's no built in function, but you can write your own

looper <- function(x, i) {
   x[ (i-1) %% length(x) + 1 ]
}

i <- c("cat", "dog", "ghost")
looper(i, 3)
# [1] "ghost"
looper(i, 4)
# [1] "cat"
looper(i, 10)
# [1] "cat"
looper(i, 11)
# [1] "dog"

This will also work with vectors of indexes

looper(i, 1:7)
# [1] "cat"   "dog"   "ghost" "cat"   "dog"   "ghost" "cat"  

And if you really want to get fancy, you could create a class and overwrite it's indexing function. For example

`[.looper` <- function(x, i) {
    x <- unclass(x)
    x[ (i-1) %% length(x) + 1 ]
}
make_looper <- function(x) {
    class(x) <- "looper"
    x
}

Then you could do

x <- make_looper(i)
x[1]
# [1] "cat"
x[2]
# [1] "dog"
x[3]
# [1] "ghost"
x[4]
# [1] "cat"

Upvotes: 5

Related Questions