@@ -40,7 +40,8 @@ and `x` is the `i`th value from the given iterator. It's useful when
4040you need not only the values `x` over which you are iterating, but
4141also the number of iterations so far. Note that `i` may not be valid
4242for indexing `iter`; it's also possible that `x != iter[i]`, if `iter`
43- has indices that do not start at 1.
43+ has indices that do not start at 1. See the `enumerate(IndexLinear(),
44+ iter)` method if you want to ensure that `i` is an index.
4445
4546```jldoctest
4647julia> a = ["a", "b", "c"];
@@ -69,6 +70,77 @@ eltype{I}(::Type{Enumerate{I}}) = Tuple{Int, eltype(I)}
6970iteratorsize {I} (:: Type{Enumerate{I}} ) = iteratorsize (I)
7071iteratoreltype {I} (:: Type{Enumerate{I}} ) = iteratoreltype (I)
7172
73+ struct IndexValue{I,A<: AbstractArray }
74+ data:: A
75+ itr:: I
76+ end
77+
78+ """
79+ enumerate(IndexLinear(), A)
80+ enumerate(IndexCartesian(), A)
81+ enumerate(IndexMethod(A), A)
82+
83+ An iterator that accesses each element of the array `A`, returning
84+ `(i, x)`, where `i` is the index for the element and `x = A[i]`. This
85+ is similar to `enumerate(A)`, except `i` will always be a valid index
86+ for `A`. Like `enumerate`, the bounds-check that would otherwise
87+ occur for `A[i]` is omitted.
88+
89+ Specifying specifying `IndexLinear()` ensures that `i` will be an
90+ integer; specifying `IndexCartesian()` ensures that `i` will be a
91+ `CartesianIndex`; specifying `IndexMethod(A)` chooses whichever has
92+ been defined as the native indexing method for array `A`.
93+
94+ ```jldoctest
95+ julia> A = ["a" "d"; "b" "e"; "c" "f"];
96+
97+ julia> for (index, value) in enumerate(IndexMethod(A), A)
98+ println("\$ index \$ value")
99+ end
100+ 1 a
101+ 2 b
102+ 3 c
103+ 4 d
104+ 5 e
105+ 6 f
106+
107+ julia> S = view(A, 1:2, :);
108+
109+ julia> for (index, value) in enumerate(IndexMethod(S), S)
110+ println("\$ index \$ value")
111+ end
112+ CartesianIndex{2}((1, 1)) a
113+ CartesianIndex{2}((2, 1)) b
114+ CartesianIndex{2}((1, 2)) d
115+ CartesianIndex{2}((2, 2)) e
116+ ```
117+
118+ Note that for a vector `v`, `enumerate(v)` returns `i` as a *counter*
119+ (always starting at 1), whereas `enumerate(IndexLinear(), v)` returns
120+ `i` as an *index* (starting at the first index of `v`, which may or
121+ may not be 1).
122+
123+ See also: [`IndexMethod`](@ref), [`indices`](@ref).
124+ """
125+ enumerate (:: IndexLinear , A:: AbstractArray ) = IndexValue (A, linearindices (A))
126+ enumerate (:: IndexCartesian , A:: AbstractArray ) = IndexValue (A, CartesianRange (indices (A)))
127+
128+ length (v:: IndexValue ) = length (v. itr)
129+ indices (v:: IndexValue ) = indices (v. itr)
130+ size (v:: IndexValue ) = size (v. itr)
131+ @inline start (v:: IndexValue ) = start (v. itr)
132+ @inline function next (v:: IndexValue , state)
133+ indx, n = next (v. itr, state)
134+ @inbounds item = v. data[indx]
135+ (indx, item), n
136+ end
137+ @inline done (v:: IndexValue , state) = done (v. itr, state)
138+
139+ eltype {I,A} (:: Type{IndexValue{I,A}} ) = Tuple{eltype (I), eltype (A)}
140+
141+ iteratorsize {I} (:: Type{IndexValue{I}} ) = iteratorsize (I)
142+ iteratoreltype {I} (:: Type{IndexValue{I}} ) = iteratoreltype (I)
143+
72144# zip
73145
74146abstract type AbstractZipIterator end
0 commit comments