如何在 Julia 中重新计算向量的 eltype

MPa*_*aga 4 julia

假设我有一个向量 v = Any[1,2,3,4]

我想以这样的方式重新计算它的 eltype typeof(v) = Vector{Int}

是否可以在无需手动连接 中的每个元素的情况下完成此操作v

phi*_*ler 5

您不能“重新输入”现有的v,只需使用更具体的类型1创建它的副本。

转换

假设您已经(静态地)知道结果类型,您有多种选择。最易读的(和 IMO,惯用的)是

Vector{Int}(v)
Run Code Online (Sandbox Code Playgroud)

这几乎相当于

convert(Vector{Int}, v)
Run Code Online (Sandbox Code Playgroud)

除了如果输入类型已经是目标类型,后者不会复制。或者:

convert.(Int, v)
Run Code Online (Sandbox Code Playgroud)

这肯定也会复制。

转换成什么

如果您知道“常见类型”是什么,则有多种选择可以获取匹配的类型。通常,typejoin可用于查找最小上限:

mapreduce(typeof, typejoin, v; init=Union{})
Run Code Online (Sandbox Code Playgroud)

结果很可能是抽象的,例如Real对于Ints 和Float64s的数组。因此,对于数字类型,您最好使用promote_type

mapreduce(typeof, promote_type, v; init=Union{})  # or init=Number
Run Code Online (Sandbox Code Playgroud)

这至少为您Float64提供了混合的Ints 和Float64s。

但是所有这些都不是真正推荐的,因为它可能是脆弱的、令人惊讶的,并且肯定不是类型稳定的。


1对于某些类型的组合,具有兼容的二进制形式,reinterpret将工作并返回具有不同类型的视图,但这仅适用于位类型,而Any不能。转换Any[1,2,3]Int[1,2,3]复制从根本上是必要的,因为这两个数组在内存中具有不同的布局:前者是指向单独分配的整数对象的指针数组,而后者将Int值内联存储在连续内存中。


DNF*_*DNF 5

如果您不知道输出类型,请考虑使用理解式

\n\n
foo(v) = [x for x in v]\n
Run Code Online (Sandbox Code Playgroud)\n\n

这在我的计算机上比以下速度快得多identity.(v)

\n\n
julia> v = Any[1,2,3,4];\n\njulia> @btime foo($v);\n  153.018 ns (2 allocations: 128 bytes)\n\njulia> @btime identity.($v);\n  293.908 ns (5 allocations: 208 bytes)\n\njulia> @btime foo(v) setup=(v=Any[rand(0:9) for _ in 1:1000]);\n  1.331 \xce\xbcs (2 allocations: 7.95 KiB)\n\njulia> @btime identity.(v) setup=(v=Any[rand(0:9) for _ in 1:1000]);\n  25.498 \xce\xbcs (494 allocations: 15.67 KiB)\n
Run Code Online (Sandbox Code Playgroud)\n