问题描述
我可以创建以下(length(X),)数组:
[F(x) for x in X]
但是,如果F(x)返回一个数组,是否有办法使用理解来创建多维数组,其中每一行都是F(x),并且数组的维数是(length(X),length(F(x))
?
解决方法
在Julia中有很多方法可以做到这一点!使用完理解后,将F(x)
的数组输出转换为二维数组的简单方法是使用vcat
,hcat
或其他方法连接结果通用cat
,并在参数上使用reduce
操作:
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
由于您专门请求了length(X)
×length(F(x))
数组,因此必须在F(x)
的输出上使用伴随运算符'
来使其正确定向到{{1 }}。您也可以对vcat
进行同样的操作并转置结果:
hcat
需要进行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
调用,因为reduce
和vcat
将它们的所有参数连接在一起-如果您只给他们hcat
,他们将假定您正在传递一个单个数组数组,并返回它,因为没有要连接的东西。
您还应该看看function broadcasting,该功能使Julia与许多其他语言不同。它可以帮助减少其他语言中依赖列表理解的代码的冗长性。只需在函数名称之后和参数之前添加一个句点,即可在参数的所有元素上自动广播函数!
[F(x) for x in X]
高级:功能组合
正如@CameronBiegnanek指出的那样,Julia使用Y = collect(2:2:10)
reduce(hcat,F.(Y))'
# 5×3 LinearAlgebra.Adjoint{Int64,2}}:
# 2 4 6
# 4 8 12
# 6 12 18
# 8 16 24
# 10 20 30
运算符支持function composition。将∘
之类的两个函数组合在一起将转换为(G ∘ F)(x)
,因此您可以使用函数G(F(x))
来组成adjoint
操作,如下所示:
F
但是这种操作(映射一个函数到数组的所有元素上,然后使用另一个函数减少所有这些输出)是一种处理数据的常用方法被称为“ map-reduce”操作。 Julia具有内置的mapreduce
功能来做到这一点!
reduce(vcat,(adjoint ∘ F).(X))
,
如果F(x)
返回一个元组或StaticArray,那么即将发布的Julia 1.6将允许您按照以下要求进行操作:
reinterpret(reshape,T,[F(x) for x in X])
演示:
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