Julia在访问数组时重新定义索引 [英] Julia redefining indices when accessing an array

查看:295
本文介绍了Julia在访问数组时重新定义索引的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个实现Array接口的结构.我想在访问它时重新定义索引.到目前为止,我已经在我的类型的Base.getindex函数中完成了此操作,但是我已经在文档中看到了Base.to_indices函数,并且不知道它们如何协同工作.

I have a structure implementing the Array interface. I want to redefine the indices when accessing it. So far, I did it in the Base.getindex function for my type, but I have seen the Base.to_indices function in the doc and do not know how they work together.

可以使用:(Colon),UnitRangeStepRangeOneToIntInt arrays访问数组元素,因此我应该在哪里重新定义索引而不必处理所有这些案件?

It is possible to access array elements using : (Colon), UnitRange, StepRange, OneTo, Int or Int arrays, so where should I redefine the indices without having to manage all these cases?

推荐答案

很难抽象地讨论这一点.这是一个具体的例子:

It's hard to talk about this in the abstract. Here's a concrete example:

struct ReversedRowMajor{T,A} <: AbstractMatrix{T}
    data::A
end
ReversedRowMajor(data::AbstractMatrix{T}) where {T} = ReversedRowMajor{T, typeof(data)}(data)
Base.size(R::ReversedRowMajor) = reverse(size(R.data))
Base.getindex(R::ReversedRowMajor, i::Int, j::Int) = R.data[end-j+1, end-i+1]

这个简单的数组访问父数组,并对其索引进行置换(将其变为行主)并进行转换(将其反转).请注意,此数组会自动支持所有预期的索引形式:

This simple array accesses the parent array with its indices permuted (to be row major) and transformed (to be reversed). Note that this array automatically supports all the expected forms of indexing:

julia> R = ReversedRowMajor([1 2; 3 4; 5 6])
2×3 ReversedRowMajor{Int64,Array{Int64,2}}:
 6  4  2
 5  3  1

julia> R[:, isodd.(R[1,:].÷2)]
2×2 Array{Int64,2}:
 6  2
 5  1

julia> @view R[[1,4,5]]
3-element view(reshape(::ReversedRowMajor{Int64,Array{Int64,2}}, 6), [1, 4, 5]) with eltype Int64:
 6
 3
 2

请注意,我们不会使用排列后的索引和计算后的索引重新索引到R中-新索引直接提供给父数组R.data.

Note that we're not re-indexing into R with the permuted and computed indices — the new indices are given directly to the parent array R.data.

现在,另一方面,to_indices将先前不受支持的索引 types 进行简单的转换,转换为IntInt的数组,然后将其重新索引为R本身那些转换后的索引.请注意当您呼叫R[Int8(1),Int8(1)]:

Now, to_indices, on the other hand, does simple transformations of previously unsupported index types to either Int or arrays of Int and then re-indexes into R itself with those transformed indices. Note what happens when you call R[Int8(1),Int8(1)]:

julia> @which R[Int8(1),Int8(1)]
getindex(A::AbstractArray, I...) in Base at abstractarray.jl:925

这没有调用您定义的任何方法-尚未.您尚未定义如何getindex(::ReversedRowMajor, ::Int8, ::Int8).因此,朱莉娅正在为您处理该案.它使用to_indicesInt8转换为Int,然后再次调用R[1,1] .现在,它会命中您定义的方法.

This isn't calling any method you defined — not yet. You didn't define how to getindex(::ReversedRowMajor, ::Int8, ::Int8). So Julia is handling that case for you. It uses to_indices to convert the Int8 to an Int and then calls R[1,1] again. Now it hits the method you defined.

简而言之:该数组具有一个简单的getindex方法和Int索引,该方法将访问重新计算为父数组.另一方面,在尚未定义匹配方法的情况下,to_indices会将所有其他类型的索引转换为支持的索引到同一数组中.您根本无法使用to_indices进行所需的转换,因为不清楚R[1, 2]是使用转换前的索引还是转换后的索引.

In short: This array has a simple getindex method with Int indices that recomputes accesses into a parent array. to_indices, on the other hand, transforms all the other types of indices to supported indices into the same array in cases where you've not defined a matching method. You're simply not able to do the sort of transformation you want with to_indices because it's not clear if R[1, 2] is using the pre-transformed indices or the post-transformed indices.

这篇关于Julia在访问数组时重新定义索引的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆