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}}
。我如何强制它使第一个子数组保持 Int64
s?在用值填充它之前,我是否需要预先定义 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]
这将创建一个实际的数据结构,它知道它包含 Float64
或 Int
数组。
一些用法
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
的向量。
我正在尝试在 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}}
。我如何强制它使第一个子数组保持 Int64
s?在用值填充它之前,我是否需要预先定义 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]
这将创建一个实际的数据结构,它知道它包含 Float64
或 Int
数组。
一些用法
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
的向量。