Reputation: 155
Say that we have an array A, that has arbitrary dimension dim(A). Say that we have a coordinate index vector V. Is there any way to access the element of A with coordinates V? Doing something like A[V] doesn't work obviously. If V=c(1,2,3) then A[V] will just give us the 1st, 2nd, and 3rd element of A. What if we want A[1,2,3] instead? If we know dim(A) ahead of time, this is easy obviously. But what if we want to make code that works no matter how many dimensions A has?
Upvotes: 1
Views: 885
Reputation: 72758
We may use do.call
to execute `[`
.
v <- c(1, 2, 3)
do.call(`[`, c(list(A), v))
# [1] 22
To assign we have `[<-`
.
A <- do.call(`[<-`, c(list(A), v, 99))
Check:
A[,,3]
# , , 3
#
# [,1] [,2] [,3]
# [1,] 19 99 25
# [2,] 20 23 26
# [3,] 21 24 27
Using @duckmayr's A
A <- array(1:(3^3), dim = c(3, 3, 3))
Upvotes: 3
Reputation: 16920
You can make use of eval(parse())
, like so:
foo <- function(A, v) {
stopifnot(length(v) == length(dim(A)))
idx <- paste(v, collapse = ", ")
return(eval(parse(text = paste0("A[", idx, "]"))))
}
A <- array(1:(3^3), dim = c(3, 3, 3))
v <- c(1, 2, 3)
foo(A, v)
# [1] 22
A[1, 2, 3]
# [1] 22
In the comments you also ask about assignment; it looks like you've got it sorted, but in case you or someone else finds it useful, you could use a replacement function:
`foo<-` <- function(A, v, value) {
stopifnot(length(v) == length(dim(A)))
stopifnot(is.atomic(value) & length(value) == 1)
idx <- paste(v, collapse = ", ")
eval(parse(text = paste0("A[", idx, "] <- value")))
return(A)
}
foo(A, v) <- 2
foo(A, v)
# [1] 2
Upvotes: 2