Julia:初始化不同类型的数值数组

Julia: Initializing numeric arrays of different types

我正在尝试在 Julia 中构建一个双元素数组,其中每个子数组都有不同的类型(一个是 Int64 的向量,另一个是 Float32 的数组s).

下面的代码自动将我想成为 Int64 的元素转换为 Float32,这是我不想要的:

my_multitype_array = [ collect(1:5), rand(Float32,3) ]

结果数组自动将第一个数组(通过collect(1:5)定义)中的Int64转换为Float32,结果my_multitype_array的类型为2-element Array{Array{Float32,1}}。我如何强制它使第一个子数组保持 Int64s?在用值填充它之前,我是否需要预先定义 my_multitype_array 为一个包含两个所需类型元素的空数组?

最后,一旦我 do 有了不同类型的所需数组,在函数中预先声明其类型时,我将如何引用它?请参阅下文了解我的意思:

function foo_function(first_scalar_arg::Float32, multiple_array_arg::Array{Array{Float32,1}})
       # do stuff
       return
end

而不是 ::Array{Array{Float32,1}},我会写 ::Array{Array{Any,1}} 还是什么?

如何实例化不同类型的向量:

如果您在终端中输入向量,它将被提升为最大的通用类型:

julia> [[1], [1.0]]
2-element Array{Array{Float64,1},1}:
 [1.0]
 [1.0]

原因是您没有指定外部向量的类型,因此 Julia 会尝试根据内容推断类型。更具体的类型总是更有效,所以如果可以将向量类型转换为可以表示所有内部向量的单一类型,这将完成(通过 promote 机制)。为避免这种情况,您需要手动指定外部向量类型,例如:

julia> Any[[1], [1.0]]
2-element Array{Any,1}:
 [1]
 [1.0]

如何引用不同类型向量的向量

仔细想想,“不同类型向量的向量”不是单一类型,而是无限类型集。这些类型在 Julia 中称为“unionall 类型”,由 where 关键字表示。在这种情况下,您需要 Vector{T} where T <: Vector.

但是等等!那怎么来的:

julia> Any[[1], [1.0]] isa Vector{T} where T <: Vector
false

嗯,可以包含任何元素的向量并不是真正的向量的向量。所以在这里你有两个选择:

  • 通过仅删除类型注释或显着重新定义它们来放松您的函数签名(这是首选,因为您传入的值实际上可能是向量的向量,即使它的类型是 Vector{Any}):
function foo_function(first_scalar_arg, multiple_array_arg::AbstractArray)
       # do stuff
       return
end
  • 否则要保持警惕,确保最初构建一个“向量的向量”:
julia> Vector[[1], [1.0]]
2-element Array{Array{T,1} where T,1}:
 [1]
 [1.0]

julia> Vector[[1], [1.0]] isa Vector{T} where T <: Vector
true

我认为以下代码更符合问题中的要求:

julia> a = Union{Array{Int},Array{Float64}}[[1,2,3],rand(2,2)]
2-element Array{Union{Array{Float64,N} where N, Array{Int64,N} where N},1}:
 [1, 2, 3]
 [0.834902264215698 0.42258382777543124; 0.5856562680004389 0.6654033155981287]

这将创建一个实际的数据结构,它知道它包含 Float64Int 数组。

一些用法

julia> a[1]
3-element Array{Int64,1}:
 1
 2
 3

julia> a[2]
2×2 Array{Float64,2}:
 0.834902  0.422584
 0.585656  0.665403

并操纵结构:

julia> push!(a, [1, 1]); #works

julia> push!(a, [true, false]);
ERROR: MethodError: no method matching Union{Array{Float64,N} where N, Array{Int64,N} where N}(::Array{Bool,1})

稍微扩展一下@Przemyslaw Szufel 的回答...

如您所见,用混合类型的元素创建向量是很棘手的,因为文字数组构造函数试图将元素提升为通用类型。有一种特殊的语法可以解决这个问题,手册中对此进行了描述 here.

对于您的情况,您可以按如下方式构造向量的向量:

julia> Union{Vector{Int64}, Vector{Float32}}[[1, 2], [1.0f0, 2.0f0]]
2-element Array{Union{Array{Float32,1}, Array{Int64,1}},1}:
 [1, 2]
 Float32[1.0, 2.0]

文字数组构造函数的前缀指定了数组的元素类型。所以在这种情况下,向量的元素类型被约束为

Union{Vector{Int64}, Vector{Float32}}

换句话说,外部向量的元素必须是Int64的向量或Float32的向量。