@@ -4,7 +4,7 @@ module Iterators
4
4
5
5
import Base: start, done, next, isempty, length, size, eltype, iteratorsize, iteratoreltype, indices, ndims
6
6
7
- using Base: tuple_type_cons, SizeUnknown, HasLength, HasShape, IsInfinite, EltypeUnknown, HasEltype, OneTo
7
+ using Base: tuple_type_cons, SizeUnknown, HasLength, HasShape, IsInfinite, EltypeUnknown, HasEltype, OneTo, @propagate_inbounds
8
8
9
9
export enumerate, zip, rest, countfrom, take, drop, cycle, repeated, product, flatten, partition
10
10
@@ -40,7 +40,8 @@ and `x` is the `i`th value from the given iterator. It's useful when
40
40
you need not only the values `x` over which you are iterating, but
41
41
also the number of iterations so far. Note that `i` may not be valid
42
42
for 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.
44
45
45
46
```jldoctest
46
47
julia> a = ["a", "b", "c"];
@@ -69,6 +70,76 @@ eltype{I}(::Type{Enumerate{I}}) = Tuple{Int, eltype(I)}
69
70
iteratorsize {I} (:: Type{Enumerate{I}} ) = iteratorsize (I)
70
71
iteratoreltype {I} (:: Type{Enumerate{I}} ) = iteratoreltype (I)
71
72
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(IndexStyle(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`.
87
+
88
+ Specifying `IndexLinear()` ensures that `i` will be an integer;
89
+ specifying `IndexCartesian()` ensures that `i` will be a
90
+ `CartesianIndex`; specifying `IndexStyle(A)` chooses whichever has
91
+ been defined as the native indexing style for array `A`.
92
+
93
+ ```jldoctest
94
+ julia> A = ["a" "d"; "b" "e"; "c" "f"];
95
+
96
+ julia> for (index, value) in enumerate(IndexStyle(A), A)
97
+ println("\$ index \$ value")
98
+ end
99
+ 1 a
100
+ 2 b
101
+ 3 c
102
+ 4 d
103
+ 5 e
104
+ 6 f
105
+
106
+ julia> S = view(A, 1:2, :);
107
+
108
+ julia> for (index, value) in enumerate(IndexStyle(S), S)
109
+ println("\$ index \$ value")
110
+ end
111
+ CartesianIndex{2}((1, 1)) a
112
+ CartesianIndex{2}((2, 1)) b
113
+ CartesianIndex{2}((1, 2)) d
114
+ CartesianIndex{2}((2, 2)) e
115
+ ```
116
+
117
+ Note that `enumerate(A)` returns `i` as a *counter* (always starting
118
+ at 1), whereas `enumerate(IndexLinear(), A)` returns `i` as an *index*
119
+ (starting at the first linear index of `A`, which may or may not be
120
+ 1).
121
+
122
+ See also: [`IndexStyle`](@ref), [`indices`](@ref).
123
+ """
124
+ enumerate (:: IndexLinear , A:: AbstractArray ) = IndexValue (A, linearindices (A))
125
+ enumerate (:: IndexCartesian , A:: AbstractArray ) = IndexValue (A, CartesianRange (indices (A)))
126
+
127
+ length (v:: IndexValue ) = length (v. itr)
128
+ indices (v:: IndexValue ) = indices (v. itr)
129
+ size (v:: IndexValue ) = size (v. itr)
130
+ @inline start (v:: IndexValue ) = start (v. itr)
131
+ @propagate_inbounds function next (v:: IndexValue , state)
132
+ indx, n = next (v. itr, state)
133
+ item = v. data[indx]
134
+ (indx, item), n
135
+ end
136
+ @inline done (v:: IndexValue , state) = done (v. itr, state)
137
+
138
+ eltype {I,A} (:: Type{IndexValue{I,A}} ) = Tuple{eltype (I), eltype (A)}
139
+
140
+ iteratorsize {I} (:: Type{IndexValue{I}} ) = iteratorsize (I)
141
+ iteratoreltype {I} (:: Type{IndexValue{I}} ) = iteratoreltype (I)
142
+
72
143
# zip
73
144
74
145
abstract type AbstractZipIterator end
0 commit comments