I can create the following (length(X),) array:
[F(x) for x in X]
However, if F(x) returns an array, is there anyway way to create a multidimensional array using comprehension where each row is F(x), and the dimensions of the array are (length(X),length(F(x))?
There are many ways to do this in Julia! Following your use of comprehensions, a simple way to turn the array output of F(x) into a 2-dimensional array would be to concatenate the results, either with vcat, hcat, or the more generic cat, and using a reduce operation over the arguments:
F(x) = [x, x*2, x*3]
X = collect(1:5)
reduce(vcat, [F(x)' for x in X])
# 5×3 Array{Int64,2}:
# 1 2 3
# 2 4 6
# 3 6 9
# 4 8 12
# 5 10 15
Because you specifically requested a length(X) by length(F(x)) array, the adjoint operator ' has to be used on the output of F(x) to orient it properly for vcat. You can also do the same with hcat and transpose the result:
reduce(hcat, [F(x) for x in X])'
# 5×3 LinearAlgebra.Adjoint{Int64,Array{Int64,2}}:
# 1 2 3
# 2 4 6
# 3 6 9
# 4 8 12
# 5 10 15
The reduce call is required because vcat and hcat concatenate together all of their arguments--if you just give them [F(x) for x in X], they will assume you are passing one single array of arrays and simply return that because there is nothing to concatenate.
You should also take a look at function broadcasting, a feature that sets Julia apart from many other languages. It can help reduce the verbosity of code that in other languages relies on list comprehensions. Just add a period after your function name and before the arguments to automatically broadcast the function over all of the elements of the argument!
Y = collect(2:2:10)
reduce(hcat, F.(Y))'
# 5×3 LinearAlgebra.Adjoint{Int64,Array{Int64,2}}:
# 2 4 6
# 4 8 12
# 6 12 18
# 8 16 24
# 10 20 30
As @CameronBiegnanek points out, Julia supports function composition using the ∘ operator. Composing two functions together like (G ∘ F)(x) translates to G(F(x)), so you can compose the adjoint operation with your function F like this:
reduce(vcat, (adjoint ∘ F).(X))
But this kind of operation (mapping a function over all elements of an array, then reducing all of those outputs using another function) is a common way of processing data known as a "map-reduce" operation. Julia has a built-in mapreduce function to do just that!
mapreduce(adjoint ∘ F, vcat, X)
If F(x) returns a tuple or a StaticArray, the upcoming Julia 1.6 will allow you to do what you're asking like this:
reinterpret(reshape, T, [F(x) for x in X])
Demo:
julia> reinterpret(reshape, Int, [(i, i+1) for i=1:4])
2×4 reinterpret(reshape, Int64, ::Vector{Tuple{Int64, Int64}}) with eltype Int64:
1 2 3 4
2 3 4 5
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With