Julia - How to index vector w/ vector of vector of indices?

Viewed 455

Suppose idxs is a vector of vectors defined as

3-element Vector{Vector{Int64}}:
 [1, 2]
 [1, 3]
 [1, 4]

And suppose A is a vector defined as

5-element Vector{Int64}:
 6
 7
 8
 9
 10

With Python and numpy, I could simply do (in pseudocode) A[idxs] and this would return a 2-D array containing the elements

[
  [6 7]
  [6 8]
  [6 9]
]

How do I perform the same indexing in Julia, where I am indexing multiple times into a 1-dimensional vector, and retrieving a matrix of entries?

Thanks

4 Answers

You can use an array comprehension with hcat. You can either use the resulting 2x3 Matrix or transpose the result.

julia> hcat([A[i] for i in id]...)'
3×2 adjoint(::Matrix{Int64}) with eltype Int64:
 6  7
 6  8
 6  9

Data

julia> show(id)
[[1, 2], [1, 3], [1, 4]]

julia> show(A)
[6, 7, 8, 9, 10]

The easiest solution would be to use list comprehension

julia> [A[i] for i in idxs]
3-element Vector{Vector{Int64}}:
 [6, 7]
 [6, 8]
 [6, 9]

In addition to the existing answers, which are good, I will note that if you can rearrange your starting indices to be a proper 2D array, rather than a vector of vectors (either along the lines of the following or by filling them into a 2D array to start with)

julia> idxs = vcat(transpose.(idxs)...)
3×2 Matrix{Int64}:
 1  2
 1  3
 1  4

then you can do this by simply directly indexing A with the 2D array of idxs:

julia> idxs
3×2 Matrix{Int64}:
 1  2
 1  3
 1  4

julia> A[idxs]
3×2 Matrix{Int64}:
 6  7
 6  8
 6  9

you could also use the underlying function behind A[i], that is getindex(A,i). you could broadcast that function and obtain what you want:

A = collect(6:10),idxs = [[1, 2], [1, 3], [1, 4]];
res = getindex.(Ref(A),idxs)

the Ref(A) is to make a "constant" element during broadcasting (broadcasting applies functions for each element of a collection with shapes, but A and idxs doesnt have the same shape. Ref(A) fixes that by behaving like an scalar)

Related