【问题标题】:Index over structures of arrays in JuliaJulia中数组结构的索引
【发布时间】:2020-05-15 12:09:34
【问题描述】:

我在 Julia 中有Timeseries 结构如下:

struct Timeseries
   timestamps::Vector{Int64}
   values::Vector{Float64}
end

我想使用如下索引定义子时间序列timeseries[i:j]

timeseries[i:j] = Timeseries(timeseries.timestamps[i:j], timeseries.values[i:j])

但是,我不想创建或复制新对象(正如values[i:j] 也不会从原始数组values 创建新数组对象)并且想使用所述语法。我该怎么做?

【问题讨论】:

  • 如果您使用的是实际的定时数据,我必须指出像 already exists 这样的结构。
  • @phipsgabler 感谢您指出这一点。我提供的示例只是我正在使用的一个简化案例,它不太适合 TimeArray 结构。

标签: julia


【解决方案1】:

如果您希望时间序列仅指向原始数据,您可以使用views。如果您稍微放宽您的类型定义,您可以允许将视图放在那里,然后为您的类型重载 Base.view

struct Timeseries{A<:AbstractVector{Int}, B<:AbstractVector{Float64}}
   timestamps::A
   values::B
end

function Base.view(t::Timeseries, idx...)
    return Timeseries(view(t.timestamps, idx...), view(t.values, idx...))
end

使用示例:

julia> ts = Timeseries(collect(1:10), collect(0.0:10.0));

julia> view(ts, 1:5)
Timeseries{SubArray{Int64,1,Array{Int64,1},Tuple{UnitRange{Int64}},true},SubArray{Float64,1,Array{Float64,1},Tuple{UnitRange{Int64}},true}}([1, 2, 3, 4, 5], [0.0, 1.0, 2.0, 3.0, 4.0])

julia> @view ts[1:5]
Timeseries{SubArray{Int64,1,Array{Int64,1},Tuple{UnitRange{Int64}},true},SubArray{Float64,1,Array{Float64,1},Tuple{UnitRange{Int64}},true}}([1, 2, 3, 4, 5], [0.0, 1.0, 2.0, 3.0, 4.0])

正如 values[i:j] 也不会从原始数组值创建新的数组对象

请注意,这不是真的——values[i:j](它调用getindex(values, i:j))给你一个新分配的数组。

【讨论】:

  • 我会建议重载 getindex 以使用视图,但这在语义上会更好。
  • 是的,并且允许您使用getindex(::Timeseries, idx) 进行复制行为。
  • 我不知道数组是从values[i:j]复制过来的。那是相当低效的内存!尽管对于许多人来说,这可能是他们想要的行为。
  • 感谢您的回答。虽然很遗憾我必须使用view(ts, 1:5) 而不是普通的ts[1:5]。最后我决定只使用ts.timestamps[1:5], ts.values[1:5] 而不是ts2.timestamps, ts2.values 代替ts2 = [1:5]
  • 我的意思是,您可以随意将view 更改为getindex 并获得ts[1:5]
猜你喜欢
  • 2021-02-27
  • 1970-01-01
  • 2016-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多