Selecting multiple elements of an array by a list of indices

I have a list of indices, say inds = [[1,2], [2,3],[4,4]] that I want to use as indices into an array. For example, if

A = reshape(1:16,4,4)

then I would want to return the values [5, 10, 16]. I can, for example, use:

[A[x[1],x[2]] for x in inds]

but that seems very clumsy; I would want something more elegant, like A[inds] (which doesn’t work). What is the canonical Julia way of pulling a list of values from an array, using a list of indices to do so? And where can I find this in the documentation? It seems as though it would be a pretty standard sort of operation, but clearly I’ve either been looking in the wrong places, or misunderstanding what I’ve been reading… Anyway, thanks!

2 Likes

A little bit less clumsy:

[A[x,y] for (x,y) in inds]
4 Likes

Thank you - yes indeed that is more elegant. But can it be done without having to explicitly reference both indices in each pair?

Not sure, but I think no, because

 getindex(A, [2, 1])

is already defined as returning A[2] and A[1] and not A[1,2].

A is an AbstractArray in above case, so you could implement getindex for AbstractMatrix.
See

julia> methods(getindex)
1 Like

Thanks again - yes, I’ve been trying all sorts of combinations, but they return either a subarray, or an error. But I’ll check on getindex. Of course, given that I know the size of my array, I could create my indices as single values i+n*(j-1) for an n by n array. That would give me inds = [5,10,16] and then A[inds] works fine. In other words, using linear indexing instead of cartesian indexing.

Quick and Dirty and only for Int:

julia> import Base.getindex

julia> getindex(A::AbstractMatrix,i::AbstractArray{Int,1}) = A[i[1],i[2]]
getindex (generic function with 199 methods)

julia> A[[1,2]]
5

A bit weird maybe but:

[A[i...] for i in inds]
4 Likes

It can be done. CartesianIndices are your best friends when it comes to indexing.

julia> inds = [[1,2], [2,3],[4,4]];

julia> A = reshape(1:16,4,4);

julia> A[CartesianIndex.(Tuple.(inds))]
3-element Array{Int64,1}:
  5
 10
 16
5 Likes

Oh thank you! I had a vague inkling that CartesianIndex might be able to help, but I couldn’t see how to do it - so it’s all done with broadcasting! Very nice indeed, and again, many thanks.

2 Likes

Thank you - clearly the triple dots hold some sort of magic of which I’m unaware. It does work though! (I’ve just discovered that this is in fact the superbly named splat operator.)