如何在Julia中缩小向量或数组的元素类型?

7

考虑这样一种情况,我首先使用eltypeAny逐步创建一个向量;之后,我想缩小其元素类型。我该如何做呢?

julia> vec = Any[1, 2, 3.]
3-element Vector{Any}:
 1
 2
 3.0

我可以使用类似 convert(Vector{Real}, vec) 的方法。但在这种情况下,我手动指定了类型,而我希望让Julia自行决定最适合的eltype

3个回答

6

可以通过在给定容器(ArrayVector)的每个元素上广播 identity 函数来实现:

julia> narrowed = identity.(vec)
3-element Vector{Real}:
 1
 2
 3.0

请注意,这不会促进(或降低)给定容器中每个单独元素的类型。
julia> typeof(narrowed[1]), typeof(narrowed[3])
(Int64, Float64)

附加点

然而,在熟悉Julia相关函数的情况下,可以通过使用typejoin函数详细地实现容器元素的类型合并。根据该函数的简明文档:

typejoin(T, S)
返回T和S的最近公共祖先,即它们都继承自的最窄类型。

typejoin的参数应为Core.Type{T}的子类型(但是,将其定义为typejoin(T...)似乎更合理,因为它可以获得无限数量的位置参数,而不仅仅是两个)。

julia> typeof.(vec)
3-element Vector{DataType}:
 Int64
 Int64
 Float64

julia> typejoin(typeof.(vec)...)
Real

julia> convert(Vector{typejoin(typeof.(vec)...)}, vec)
3-element Vector{Real}:
 1
 2
 3.0

2

在Julia中,处理小型联合类型(例如Union{Int, Float64})比抽象类型更快,因此您应该避免使用抽象元素的向量,如Vector{Real},而是使用具体类型的联合类型,如Union{Int, Float64}

话虽如此,这里有一段代码可以生成这样的联合类型:

julia> Vector{Union{Set(typeof.(vec))...}}(vec)
3-element Vector{Union{Float64, Int64}}:
 1
 2
 3.0

这里有一个简单的测试,表明对于一个100元素向量,性能差异为4倍:

julia> a1 = Vector{Union{Int, Float64}}(rand(100));

julia> a2 = Vector{Real}(rand(100));

julia> @btime minimum($a1);
  428.643 ns (0 allocations: 0 bytes)

julia> @btime minimum($a2);
  2.000 μs (102 allocations: 1.59 KiB)

0
您可以像这样使用promote:

v = Any[1, 2, 3.0]
first.(promote.(v))
3-element Vector{Real}:
 1
 2
 3.0000

v = Any[1, 2, 3.0, 3 + 2im]
first.(promote.(v))
4-element Vector{Number}:
   1
   2
   3.0000
 3 + 2im

但是,您可能更感兴趣的是获取元素的具体超类型向量,特别是出于性能考虑。因此,您可以使用以下内容:

v = Any[1, 2, 3.0]
reduce(vcat, promote(v...))
3-element Vector{Float64}:
 1.0
 2.0
 3.0

v = Any[1, 2, 3.0, 3 + 2im]
reduce(vcat, promote(v...))
4-element Vector{ComplexF64}:
 1.0 + 0.0im
 2.0 + 0.0im
 3.0 + 0.0im
 3.0 + 2.0im

或者,简单点:

v = Any[1, 2, 3.0];

[v...]
3-element Vector{Float64}:
 1.0
 2.0
 3.0

v = Any[1, 2, 3.0, 3+2im];

[v...]
4-element Vector{ComplexF64}:
 1.0 + 0.0im
 2.0 + 0.0im
 3.0 + 0.0im
 3.0 + 2.0im

列表推导式也适用于第一种选项:[i for i in v] - AboAmmar
谢谢。但这不是缩小范围,这实际上是促进。你正在改变元素。 - Shayan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接