在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)
(有更好的方法吗?)但是如何以通用的方式跳过最后一个?
答案 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]