如何迭代除AbstractArray的最后一个索引之外的所有索引

时间:2017-04-26 17:36:53

标签: iteration julia

在Julia中,迭代AbstractArray的所有索引的推荐方法是使用eachindex,例如,

for i in eachindex(a)
    do_something(a[i], i)
end

1:length(a)相比,eachindex(a)支持具有非常规索引的数组,即不从1开始的索引。此外,对于具有慢线性索引的数组,它更有效。

如果我想跳过第一个索引,我可以使用Iterators.drop(eachindex(a), 1)(有更好的方法吗?)但是如何以通用的方式跳过最后一个?

3 个答案:

答案 0 :(得分:5)

A"前线"迭代器相对简单并且通常很有用。 编辑:仅针对此案例完全具体地定义它也是完全过分的。依靠Base的内置函数更容易,更简单,定义如下:

front(itr, n=1) = Iterators.take(itr, length(itr)-n)

这适用于定义了length的所有迭代器 - 其中包含eachindex将返回的所有内容。

或者,您可以从不依赖于length定义的第一原则定义专用迭代器。我不知道任何现有包中的这种结构。使用Julia 0.6,实现可能看起来像:

struct Front{T}
    itr::T
end
# Basic iterator definition
function Base.start(f::Front)
    s = start(f.itr)
    done(f.itr, s) && throw(ArgumentError("cannot take the front of an empty iterator"))
    return next(f.itr, s)
end
function Base.next(f::Front, state)
    val, s = state
    return val, next(f.itr, s)
end
Base.done(f::Front, state) = done(f.itr, state[2])

# Inherit traits as appropriate
Base.iteratorsize(::Type{Front{T}}) where {T} = _dropshape(Base.iteratorsize(T))
_dropshape(x) = x
_dropshape(::Base.HasShape) = Base.HasLength()
Base.iteratoreltype(::Type{Front{T}}) where {T} = Base.iteratoreltype(T)
Base.length(f::Front) = length(f.itr) - 1
Base.eltype(f::Front{T}) where {T} = eltype(T)

现在:

julia> collect(Front(eachindex(rand(5))))
4-element Array{Int64,1}:
 1
 2
 3
 4

julia> collect(Front(eachindex(sprand(3, 2, .2))))
5-element Array{CartesianIndex{2},1}:
 CartesianIndex{2}((1, 1))
 CartesianIndex{2}((2, 1))
 CartesianIndex{2}((3, 1))
 CartesianIndex{2}((1, 2))
 CartesianIndex{2}((2, 2))

答案 1 :(得分:1)

定义@MattB的另一种方式。Front

front(itr,n=1) = (first(x) for x in Iterators.partition(itr,n+1,1))

这也给出了:

julia> front(eachindex([1,2,3,4,5]))|>collect
4-element Array{Int64,1}:
 1
 2
 3
 4

并作为奖励:

julia> front(eachindex([1,2,3,4,5]),2)|>collect
3-element Array{Int64,1}:
 1
 2
 3

drop(eachindex([1,2,3,4,5]),2)的相应迭代器。

答案 2 :(得分:1)

还有以下内容:

for I in CartesianRange(Base.front(indices(A))) @show I A[I, :] end

A = reshape(1:27, 3, 3, 3)上,这会产生

I = CartesianIndex{2}((1,1)) A[I,:] = [1,10,19] I = CartesianIndex{2}((2,1)) A[I,:] = [2,11,20] I = CartesianIndex{2}((3,1)) A[I,:] = [3,12,21] I = CartesianIndex{2}((1,2)) A[I,:] = [4,13,22] I = CartesianIndex{2}((2,2)) A[I,:] = [5,14,23] I = CartesianIndex{2}((3,2)) A[I,:] = [6,15,24] I = CartesianIndex{2}((1,3)) A[I,:] = [7,16,25] I = CartesianIndex{2}((2,3)) A[I,:] = [8,17,26] I = CartesianIndex{2}((3,3)) A[I,:] = [9,18,27]