我对不同类型的数组数组感到困惑。考虑这两个例子
a = Array{Float64}[]
push!(a,[1, 2])
push!(a,[3, 4])
push!(a,[1 2; 3 4])
b = Array[[1.0, 2.0], [3.0,4.0], [1.0 2.0; 3.0 4.0]]
Run Code Online (Sandbox Code Playgroud)
我不确定如何a和b不同。假设我打算对aor 中的b每个元素运行一个 for 循环,并将每个元素乘以 2。也就是说,
for i in 1:3 a[i] = a[i]*2 end
for i in 1:3 b[i] = b[i]*2 end
Run Code Online (Sandbox Code Playgroud)
我分别为两条线的运行时间计时,但它们同样快。是a和b一样吗?如果是这样,为什么a甚至存在?它看起来相当复杂,因为typeof(a)产生“Array{Array{Float64,N} where N,1}”。where在这里做什么?
两个a和b是矢量,但它们允许不同类型的元件。你可以通过写来检查这一点:
julia> typeof(a)
Array{Array{Float64,N} where N,1}
julia> typeof(b)
Array{Array,1}
Run Code Online (Sandbox Code Playgroud)
现在Array是带两个参数的参数类型。第一个参数是它允许的元素类型。第二个参数是维度。您可以看到,在这两种情况下,维数都1意味着a和b都是向量。您还可以使用以下ndims功能检查它:
julia> ndims(a)
1
julia> ndims(b)
1
Run Code Online (Sandbox Code Playgroud)
第一个参数是允许的元素类型。在a它的情况下,Array{Float64,N} where N而在b只是Array打印的情况下。在我解释如何阅读它们之前,请注意可以使用该eltype函数提取第一个参数:
julia> eltype(a)
Array{Float64,N} where N
julia> eltype(b)
Array
Run Code Online (Sandbox Code Playgroud)
你可以看到,无论是a和b允许Array存储。首先让我解释一下如何阅读Array{Float64, N} where N。这意味着a允许存储Float64任何维度的数组。实际上,您可以像这样Array{Float64}以更短的方式编写,因为您可以检查:
julia> (Array{Float64,N} where N) === Array{Float64}
true
Run Code Online (Sandbox Code Playgroud)
原因是如果您不对尾部参数设置限制,则可以在语法中删除它。该where N部分是对参数的限制。在这种情况下,对第二个参数没有限制。
现在我们可以转向b. 您会看到它eltype只是Array,因此两个参数都被删除,因此如上所述对它们没有限制。所以和你在这里看到Array的一样Array{T, N} where {T,N}:
julia> (Array{T, N} where {T,N}) === Array
true
Run Code Online (Sandbox Code Playgroud)
所以区别在于a可以存储任意维度的数组但必须具有Float64元素类型,而b可以存储任意维度和任意元素类型的数组。在这种情况下,这种区别对性能没有影响,但会影响a和 中可以存储的内容b。这里有些例子。
在这种情况下,它们的工作方式与您尝试Int在其中存储 an 相同,但它们仅允许使用数组:
julia> a[1] = 1
ERROR: MethodError: Cannot `convert` an object of type
julia> b[1] = 1
ERROR: MethodError: Cannot `convert` an object of type
Run Code Online (Sandbox Code Playgroud)
但在这里他们有所不同:
julia> a[1] = ["a"]
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Float64
julia> b[1] = ["a"]
1-element Array{String,1}:
"a"
julia> a
3-element Array{Array{Float64,N} where N,1}:
[1.0, 2.0]
[3.0, 4.0]
[1.0 2.0; 3.0 4.0]
julia> b
3-element Array{Array,1}:
["a"]
[3.0, 4.0]
[1.0 2.0; 3.0 4.0]
Run Code Online (Sandbox Code Playgroud)
如您所见,您可以存储一个Stringin数组b,但不允许将其存储在a.
两个额外的评论(两个主题都有点复杂,所以我省略了细节,但只是给你提示正在发生的事情):
julia> [[1.0, 2.0], [3.0,4.0], [1.0 2.0; 3.0 4.0]]
3-element Array{Array{Float64,N} where N,1}:
[1.0, 2.0]
[3.0, 4.0]
[1.0 2.0; 3.0 4.0]
Run Code Online (Sandbox Code Playgroud)
数组元素类型选择对性能的影响取决于以下事实:
isabstracttype; 这会影响编译器做出的类型推断),isbitstype;这会影响存储布局),Union(可以更有效地处理小联合)。在您的情况下,两种元素类型都是抽象的和非位的,因此性能是相同的。