2017-02-14 18 views
3

У меня есть некоторые специально определенные массивы в Юлии, которые вы можете представить как просто состав многих массивов. Например:Итерация для `setindex!`

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 против y и индекса, а также построение eachindex итератор, который, похоже на то, что CatViews.jl does. Однако я не уверен, как это будет взаимодействовать с отправкой i... или будет ли это полезно в этом случае.

Кроме того, будет ли широковещательная передача автоматически использовать эту быструю схему итерации, если она построена на eachindex?

изменения:

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

В реальном случае, x может быть любой AbstractArray (и, таким образом, имеет линейный индекс), но так как используется только линейная индексация (для этого одного пользователя обращенных getindex функции, за исключением), проблема действительно сводится к выяснению, как это сделать с помощью x a Vector.

+0

Каково определение 'length (c)' и задано естественное, что происходит, когда вы 'getindex (c, i)' когда 'i> length (c.x) + length (c.y)'? Кроме того, 'c.x [i ...]' является странным, поскольку 'c.x' является вектором i.e измерения 1. Вы можете сделать вопрос более ясным. –

+0

О, была ошибка в индексировании. Исправлена. –

ответ

7

Создание X[CartesianIndex(2,1)] означает что-то отличное от X[2,1], конечно, не закончится хорошо. И я ожидал бы подобных неприятностей из-за того, что X[100,1] может означать что-то отличное от X[100] или если length(X) != prod(size(X)). Вы можете нарушать правила, но не удивляйтесь, когда функции в Базе и других пакетах ожидают, что вы последуете за ними.

Безопасный способ сделать это - сделать eachindex(::CompositeArray) вернуть пользовательский итератор по объектам, которые вы полностью контролируете. Может быть, просто бросьте обертку вокруг и переместите методы на CartesianRange и CartesianIndex{2}, если эта структура данных полезна. Затем, когда вы получаете один из этих настраиваемых типов индексов, вы знаете, что SplitIndex(CartesianIndex(1,2)) действительно намеревается ссылаться на первый элемент во втором массиве.

+0

О, я вижу. «Безопасный способ сделать это - заставить everyindex (:: CompositeArray) возвращать пользовательский итератор поверх объектов, которые вы полностью контролируете». Под этим вы подразумеваете, создаете неизменяемый и новый 'getindex' на этом типе и используете это в' eachindex'? Похоже, это сработает. –

+0

Yup, точно. - –