迭代`setindex!`

时间:2017-02-14 13:29:19

标签: arrays iterator julia

我在Julia中有一些特殊定义的数组,你可以认为它只是许多数组的组合。例如:

type CompositeArray{T}
  x::Vector{T}
  y::Vector{T}
end

使用索引方案

getindex(c::CompositeArray,i::Int) = i <= length(c) ? c.x[i] : c.y[i-length(c.x)]

我有一点需要注意:较高的索引方案只是x本身:

getindex(c::CompositeArray,i::Int...) = c.x[i...]

现在,通过它们的迭代器可以很容易地作为迭代器的链在x上,然后在y上。这使得迭代值几乎不需要额外的成本。但是,迭代到setindex!可以做类似的事情吗?

我正考虑在CartesianIndex{2}上单独发送,仅用于索引x vs y和索引,并为此构建eachindex迭代器,类似于CatViews.jl does。但是,我不确定它将如何与i...调度交互,或者在这种情况下是否有用。

此外,如果它是基于eachindex构建的,广播会自动使用这种快速迭代方案吗?

编辑:

length(c::CompositeArray) = length(c.x) + length(c.y)

在实际情况中,x可以是任何AbstractArray(因此具有线性索引),但由于仅使用线性索引(除了那个面向用户{{1}这个问题真的归结为找出如何使用getindex向量来做到这一点。

1 个答案:

答案 0 :(得分:7)

使X[CartesianIndex(2,1)]意味着与X[2,1]不同的东西肯定不会结束。我希望X[100,1]可能意味着与X[100]length(X) != prod(size(X))不同的事实会带来类似的麻烦。您可以自由地违反规则,但是当Base和其他软件包中的函数希望您遵循它们时,您不应该感到惊讶。

执行此操作的安全方法是使eachindex(::CompositeArray)在您完全控制的对象上返回自定义迭代器。如果该数据结构有用,可能只是向CartesianRangeCartesianIndex{2}抛出一个包装器并转发方法。然后,当您获得其中一个自定义索引类型时,您知道SplitIndex(CartesianIndex(1,2))确实打算引用第二个数组中的第一个元素。

相关问题