# How to extract components in an array of arrays

Suppose I have an array of arrays, say a 2 x 2 matrix whose entries are 1 x 2 vectors, e.g.,

``````julia> A
2×2 Matrix{Matrix{Int64}}:
[1 2]  [3 4]
[5 6]  [7 8]
``````

I am wondering, without using `for` loops, how to extract a 2 x 2 matrix consisting of the 1st entries of this matrix of matrices, i.e.,

``````2x2 Matrix{Int64}
1 3
5 7
``````

Also, a matrix of its 2nd entries, i.e.,

``````2x2 Matrix{Int64}
2 4
6 8
``````

Is there a nice and quick way to do this? (Of course, what I really want is to do the same for large matrices of matrices or vectors, but this 2x2 example sufficiently describe my intention.)

You can broadcast `getindex.(A,1)` which gets index 1 for each element of the array.

2 Likes

Thank you so much! This is quite helpful!

Specifically for the first and last elements, you can use `first.(A)` and `last.(A)`.

BTW, there’s no such thing as a 1x2 vector. That is a matrix.

1 Like

Note that in Julia vocab, `[1 2]` is not a vector but a 1x2 matrix. If you don’t have a specific reason to store your data like this, using `[1, 2]` is more Julian.

1 Like

what is (are they?) the syntax to use to build by hand a matrix like A that has matrices as elements?

The following reproduces `A`:

``````A = [[[1 2]] [[3 4]]; [[5 6]] [[7 8]]]
``````
1 Like

I have tried these ways, but one doesn’t work and I didn’t like the other as much

``````julia> [[1 2] [3 4]; [5 6] [7 8]]
2×4 Matrix{Int64}:
1  2  3  4
5  6  7  8

julia> reshape([[1 2], [5 6], [3 4], [7 8]],2,2)
2×2 Matrix{Matrix{Int64}}:
[1 2]  [3 4]
[5 6]  [7 8]
``````

instead, this creates an array of tuples.
Why in the case of vectors need to be wrapped inside another vector?

``````julia> [(1,2) (3,4); (5,6) (7,8)]
2×2 Matrix{Tuple{Int64, Int64}}:
(1, 2)  (3, 4)
(5, 6)  (7, 8)
``````

anhoter way

``````julia> [[[1 2], [5 6]] [ [3 4], [7 8]]]
2×2 Matrix{Matrix{Int64}}:
[1 2]  [3 4]
[5 6]  [7 8]
``````

I think this follows from Julia’s rule that square braces surrounding elements separated by spaces are equivalent to horizontal concatenation:

``````[A B] == hcat(A,B)
``````
2 Likes

Thanks, you are right. What I meant was row vectors of length 2, which are 1 x 2 matrices.

BTW, what I really wanted to do is to generate a vector field on a 2D plane, say, the unit square, and draw that vector field using `quiver` plot in Plots.jl. So, here is an example on a very small grid.

``````julia> using LazyGrids # this allows to generate meshes like in MATLAB
julia> X, Y = ndgrid((collect(0:1), collect(0:1));
julia> X
2×2 LazyGrids.GridAV{Int64, 1, 2}:
0  0
1  1
julia> Y
2×2 LazyGrids.GridAV{Int64, 2, 2}:
0  1
0  1
julia> f(x,y) = [0.0 1.0; 1.0 0.0] * [x; y]; # Just a simple example of generating a vector at (x,y).
julia> A =  f.(X,Y) # pointwise evaluation of f on the mesh
2×2 Matrix{Vector{Float64}}:
[0.0, 0.0]  [1.0, 0.0]
[0.0, 1.0]  [1.0, 1.0]
``````

Then, in order to use `quiver` plot, I need to extract the first components and the second components:

``````quiver(X[:], Y[:], quiver=(getindex.(A,1)[:], getindex.(A,2)[:]))
``````

Perhaps, there is a better way to generate a vector field, which can easily supply to the `quiver` plot…

It should be more convenient to work with vectors as they are, instead of separate components:

``````julia> using RectiGrids
julia> using StaticArrays

# array of SVectors, instead of two separate arrays:
julia> XY = grid(SVector, 0:1, 0:1)
2-dimensional KeyedArray(...) with keys:
↓   2-element UnitRange{Int64}
→   2-element UnitRange{Int64}
And data, 2×2 RectiGrids.RectiGridArr{Base.OneTo(2), SVector{2, Int64}, 2, Tuple{UnitRange{Int64}, UnitRange{Int64}}}:
(0)        (1)
(0)     [0, 0]     [0, 1]
(1)     [1, 0]     [1, 1]

# f() takes the whole svector, not two separate components:
julia> f(xy) = [0. 1; 1 0] * xy
f (generic function with 1 method)

julia> A = f.(XY)
2-dimensional KeyedArray(...) with keys:
↓   2-element UnitRange{Int64}
→   2-element UnitRange{Int64}
And data, 2×2 Matrix{Vector{Float64}}:
(0)            (1)
(0)     [0.0, 0.0]     [1.0, 0.0]
(1)     [0.0, 1.0]     [1.0, 1.0]
``````

Only in the end, if you actually need to split them into components:

``````julia> using SplitApplyCombine

julia> invert(XY)
2-element Vector{Matrix{Int64}}:
[0 0; 1 1]
[0 1; 0 1]

julia> invert(A)
2-element Vector{Matrix{Float64}}:
[0.0 1.0; 0.0 1.0]
[0.0 0.0; 1.0 1.0]
``````