1

Given an array as follows:

A = Array{Array{Int}}(2,2)
A[1,1] = [1,2]
A[1,2] = [3,4]
A[2,1] = [5,6]
A[2,2] = [7,8]

We then have that A is a 2x2 array with elements of type Array{Int}:

2×2 Array{Array{Int64,N} where N,2}:
 [1, 2]  [3, 4]
 [5, 6]  [7, 8]

It is possible to access the entries with e.g. A[1,2] but A[1,2,2] would not work since the third dimension is not present in A. However, A[1,2][2] works, since A[1,2] returns an array of length 2.

The question is then, what is a nice way to convert A into a 3-dimensional array, B, so that B[i,j,k] refers the the i,j-th array and the k-th element in that array. E.g. B[2,1,2] = 6.

There is a straightforward way to do this using 3 nested loops and reconstructing the array, element-by-element, but I'm hoping there is a nicer construction. (Some application of cat perhaps?)

3
  • 1
    cat(3,first.(A),last.(A)) also gives the same matrix. If more than two elements in internal vectors, getindex can be used to generalize this construction. Commented Nov 10, 2017 at 13:58
  • I figured out one way: B = permutedims(reshape(collect(Iterators.flatten(A)), (2,2,2)), [3,2,1]), but it is very badly readable and I'd rather use the generators from @durand's answer below. To generalise your answer: cat(3, map(idx -> getindex.(A, idx),(1:2))...) may be alright (for suitable ranges). Commented Nov 10, 2017 at 14:43
  • 1
    The expressions in your comment can also be written: permutedims(reshape(vcat(A...),2,2,2),[2,3,1]) and cat(3,(getindex.(A,i) for i=1:2)...) Commented Nov 10, 2017 at 14:56

3 Answers 3

2

You can construct a 3-d array from A using an array comprehension

julia> B = [ A[i,j][k] for i=1:2, j=:1:2, k=1:2 ]
2×2×2 Array{Int64,3}:
[:, :, 1] =
 1  3
 5  7

[:, :, 2] =
 2  4
 6  8

julia> B[2,1,2]
6

However a more general solution would be to overload the getindex function for arrays with the same type of A. This is more efficient since there is no need to copy the original data.

julia> import Base.getindex

julia> getindex(A::Array{Array{Int}}, i::Int, j::Int, k::Int) = A[i,j][k]
getindex (generic function with 179 methods)

julia> A[2,1,2]
6
Sign up to request clarification or add additional context in comments.

Comments

0

With thanks to Dan Getz's comments, I think the following works well and is succinct:

cat(3,(getindex.(A,i) for i=1:2)...)

where 2 is the length of the nested array. It would also work for higher dimensions.

Comments

0

permutedims(reshape(collect(Base.Iterators.flatten(A)), (2,2,2)), (2,3,1))

also does the job and appears to be faster than the accepted cat() answer for me.

EDIT: I'm sorry, I just saw that this has already been suggested in the comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.