OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of dart.core; | 5 part of dart.core; |
6 | 6 |
7 /** | 7 /** |
8 * The [Iterable] interface allows to get an [Iterator] out of an | 8 * The [Iterable] interface allows to get an [Iterator] out of an |
9 * [Iterable] object. | 9 * [Iterable] object. |
10 * | 10 * |
(...skipping 30 matching lines...) Expand all Loading... |
41 /** | 41 /** |
42 * Returns a lazy [Iterable] where each element [:e:] of [this] is replaced | 42 * Returns a lazy [Iterable] where each element [:e:] of [this] is replaced |
43 * by the result of [:f(e):]. | 43 * by the result of [:f(e):]. |
44 * | 44 * |
45 * This method returns a view of the mapped elements. As long as the | 45 * This method returns a view of the mapped elements. As long as the |
46 * returned [Iterable] is not iterated over, the supplied function [f] will | 46 * returned [Iterable] is not iterated over, the supplied function [f] will |
47 * not be invoked. The transformed elements will not be cached. Iterating | 47 * not be invoked. The transformed elements will not be cached. Iterating |
48 * multiple times over the the returned [Iterable] will invoke the supplied | 48 * multiple times over the the returned [Iterable] will invoke the supplied |
49 * function [f] multiple times on the same element. | 49 * function [f] multiple times on the same element. |
50 */ | 50 */ |
51 Iterable map(f(E element)) => new MappedIterable<E, dynamic>(this, f); | 51 Iterable map(f(E element)); |
52 | 52 |
53 /** | 53 /** |
54 * Returns a lazy [Iterable] with all elements that satisfy the | 54 * Returns a lazy [Iterable] with all elements that satisfy the |
55 * predicate [f]. | 55 * predicate [f]. |
56 * | 56 * |
57 * This method returns a view of the mapped elements. As long as the | 57 * This method returns a view of the mapped elements. As long as the |
58 * returned [Iterable] is not iterated over, the supplied function [f] will | 58 * returned [Iterable] is not iterated over, the supplied function [f] will |
59 * not be invoked. Iterating will not cache results, and thus iterating | 59 * not be invoked. Iterating will not cache results, and thus iterating |
60 * multiple times over the the returned [Iterable] will invoke the supplied | 60 * multiple times over the the returned [Iterable] will invoke the supplied |
61 * function [f] multiple times on the same element. | 61 * function [f] multiple times on the same element. |
62 */ | 62 */ |
63 Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f); | 63 Iterable<E> where(bool f(E element)); |
64 | |
65 | 64 |
66 /** | 65 /** |
67 * Expand each element of this [Iterable] into zero or more elements. | 66 * Expand each element of this [Iterable] into zero or more elements. |
68 * | 67 * |
69 * The resulting Iterable will run through the elements returned | 68 * The resulting Iterable will run through the elements returned |
70 * by [f] for each element of this, in order. | 69 * by [f] for each element of this, in order. |
71 * | 70 * |
72 * The returned [Iterable] is lazy, and will call [f] for each element | 71 * The returned [Iterable] is lazy, and will call [f] for each element |
73 * of this every time it's iterated. | 72 * of this every time it's iterated. |
74 */ | 73 */ |
75 Iterable expand(Iterable f(E element)) => | 74 Iterable expand(Iterable f(E element)); |
76 new ExpandIterable<E, dynamic>(this, f); | |
77 | 75 |
78 /** | 76 /** |
79 * Check whether the collection contains an element equal to [element]. | 77 * Check whether the collection contains an element equal to [element]. |
80 */ | 78 */ |
81 bool contains(E element) { | 79 bool contains(E element); |
82 for (E e in this) { | |
83 if (e == element) return true; | |
84 } | |
85 return false; | |
86 } | |
87 | 80 |
88 /** | 81 /** |
89 * Applies the function [f] to each element of this collection. | 82 * Applies the function [f] to each element of this collection. |
90 */ | 83 */ |
91 void forEach(void f(E element)) { | 84 void forEach(void f(E element)); |
92 for (E element in this) f(element); | |
93 } | |
94 | 85 |
95 /** | 86 /** |
96 * Reduce a collection to a single value by iteratively combining elements | 87 * Reduces a collection to a single value by iteratively combining elements |
97 * of the collection using the provided function. | 88 * of the collection using the provided function. |
98 * | 89 * |
99 * Example of calculating the sum of an iterable: | 90 * Example of calculating the sum of an iterable: |
100 * | 91 * |
101 * iterable.reduce((value, element) => value + element); | 92 * iterable.reduce((value, element) => value + element); |
102 * | 93 * |
103 */ | 94 */ |
104 E reduce(E combine(E value, E element)) { | 95 E reduce(E combine(E value, E element)); |
105 Iterator<E> iterator = this.iterator; | |
106 if (!iterator.moveNext()) { | |
107 throw new StateError("No elements"); | |
108 } | |
109 E value = iterator.current; | |
110 while (iterator.moveNext()) { | |
111 value = combine(value, iterator.current); | |
112 } | |
113 return value; | |
114 } | |
115 | 96 |
116 /** | 97 /** |
117 * Reduce a collection to a single value by iteratively combining each element | 98 * Reduces a collection to a single value by iteratively combining each |
118 * of the collection with an existing value using the provided function. | 99 * element of the collection with an existing value using the provided |
| 100 * function. |
| 101 * |
119 * Use [initialValue] as the initial value, and the function [combine] to | 102 * Use [initialValue] as the initial value, and the function [combine] to |
120 * create a new value from the previous one and an element. | 103 * create a new value from the previous one and an element. |
121 * | 104 * |
122 * Example of calculating the sum of an iterable: | 105 * Example of calculating the sum of an iterable: |
123 * | 106 * |
124 * iterable.fold(0, (prev, element) => prev + element); | 107 * iterable.fold(0, (prev, element) => prev + element); |
125 * | 108 * |
126 */ | 109 */ |
127 dynamic fold(var initialValue, | 110 dynamic fold(var initialValue, |
128 dynamic combine(var previousValue, E element)) { | 111 dynamic combine(var previousValue, E element)); |
129 var value = initialValue; | |
130 for (E element in this) value = combine(value, element); | |
131 return value; | |
132 } | |
133 | 112 |
134 /** | 113 /** |
135 * Returns true if every elements of this collection satisify the | 114 * Returns true if every elements of this collection satisify the |
136 * predicate [f]. Returns false otherwise. | 115 * predicate [f]. Returns false otherwise. |
137 */ | 116 */ |
138 bool every(bool f(E element)) { | 117 bool every(bool f(E element)); |
139 for (E element in this) { | |
140 if (!f(element)) return false; | |
141 } | |
142 return true; | |
143 } | |
144 | 118 |
145 /** | 119 /** |
146 * Convert each element to a [String] and concatenate the strings. | 120 * Converts each element to a [String] and concatenates the strings. |
147 * | 121 * |
148 * Converts each element to a [String] by calling [Object.toString] on it. | 122 * Converts each element to a [String] by calling [Object.toString] on it. |
149 * Then concatenates the strings, optionally separated by the [separator] | 123 * Then concatenates the strings, optionally separated by the [separator] |
150 * string. | 124 * string. |
151 */ | 125 */ |
152 String join([String separator = ""]) { | 126 String join([String separator = ""]) { |
153 StringBuffer buffer = new StringBuffer(); | 127 StringBuffer buffer = new StringBuffer(); |
154 buffer.writeAll(this, separator); | 128 buffer.writeAll(this, separator); |
155 return buffer.toString(); | 129 return buffer.toString(); |
156 } | 130 } |
157 | 131 |
158 /** | 132 /** |
159 * Returns true if one element of this collection satisfies the | 133 * Returns true if one element of this collection satisfies the |
160 * predicate [f]. Returns false otherwise. | 134 * predicate [f]. Returns false otherwise. |
161 */ | 135 */ |
162 bool any(bool f(E element)) { | 136 bool any(bool f(E element)); |
163 for (E element in this) { | |
164 if (f(element)) return true; | |
165 } | |
166 return false; | |
167 } | |
168 | 137 |
169 List<E> toList({ bool growable: true }) => | 138 /** |
170 new List<E>.from(this, growable: growable); | 139 * Creates a [List] containing the elements of this [Iterable]. |
171 Set<E> toSet() => new Set<E>.from(this); | 140 * |
| 141 * The elements will be in iteration order. The list is fixed-length |
| 142 * if [growable] is false. |
| 143 */ |
| 144 List<E> toList({ bool growable: true }); |
| 145 |
| 146 /** |
| 147 * Creates a [Set] containing the elements of this [Iterable]. |
| 148 */ |
| 149 Set<E> toSet(); |
172 | 150 |
173 /** | 151 /** |
174 * Returns the number of elements in [this]. | 152 * Returns the number of elements in [this]. |
175 * | 153 * |
176 * Counting all elements may be involve running through all elements and can | 154 * Counting all elements may be involve running through all elements and can |
177 * therefore be slow. | 155 * therefore be slow. |
178 */ | 156 */ |
179 int get length { | 157 int get length; |
180 int count = 0; | |
181 Iterator it = iterator; | |
182 while (it.moveNext()) { | |
183 count++; | |
184 } | |
185 return count; | |
186 } | |
187 | 158 |
188 /** | 159 /** |
189 * Returns true if there is no element in this collection. | 160 * Returns true if there is no element in this collection. |
190 */ | 161 */ |
191 bool get isEmpty => !iterator.moveNext(); | 162 bool get isEmpty; |
192 | 163 |
193 /** | 164 /** |
194 * Returns an [Iterable] with at most [n] elements. | 165 * Returns an [Iterable] with at most [n] elements. |
195 * | 166 * |
196 * The returned [Iterable] may contain fewer than [n] elements, if [this] | 167 * The returned [Iterable] may contain fewer than [n] elements, if [this] |
197 * contains fewer than [n] elements. | 168 * contains fewer than [n] elements. |
198 */ | 169 */ |
199 Iterable<E> take(int n) { | 170 Iterable<E> take(int n); |
200 return new TakeIterable<E>(this, n); | |
201 } | |
202 | 171 |
203 /** | 172 /** |
204 * Returns an [Iterable] that stops once [test] is not satisfied anymore. | 173 * Returns an [Iterable] that stops once [test] is not satisfied anymore. |
205 * | 174 * |
206 * The filtering happens lazily. Every new [Iterator] of the returned | 175 * The filtering happens lazily. Every new [Iterator] of the returned |
207 * [Iterable] will start iterating over the elements of [this]. | 176 * [Iterable] will start iterating over the elements of [this]. |
208 * When the iterator encounters an element [:e:] that does not satisfy [test], | 177 * When the iterator encounters an element [:e:] that does not satisfy [test], |
209 * it discards [:e:] and moves into the finished state. That is, it will not | 178 * it discards [:e:] and moves into the finished state. That is, it will not |
210 * ask or provide any more elements. | 179 * ask or provide any more elements. |
211 */ | 180 */ |
212 Iterable<E> takeWhile(bool test(E value)) { | 181 Iterable<E> takeWhile(bool test(E value)); |
213 return new TakeWhileIterable<E>(this, test); | |
214 } | |
215 | 182 |
216 /** | 183 /** |
217 * Returns an [Iterable] that skips the first [n] elements. | 184 * Returns an [Iterable] that skips the first [n] elements. |
218 * | 185 * |
219 * If [this] has fewer than [n] elements, then the resulting [Iterable] will | 186 * If [this] has fewer than [n] elements, then the resulting [Iterable] will |
220 * be empty. | 187 * be empty. |
221 */ | 188 */ |
222 Iterable<E> skip(int n) { | 189 Iterable<E> skip(int n); |
223 return new SkipIterable<E>(this, n); | |
224 } | |
225 | 190 |
226 /** | 191 /** |
227 * Returns an [Iterable] that skips elements while [test] is satisfied. | 192 * Returns an [Iterable] that skips elements while [test] is satisfied. |
228 * | 193 * |
229 * The filtering happens lazily. Every new [Iterator] of the returned | 194 * The filtering happens lazily. Every new [Iterator] of the returned |
230 * [Iterable] will iterate over all elements of [this]. | 195 * [Iterable] will iterate over all elements of [this]. |
231 * As long as the iterator's elements do not satisfy [test] they are | 196 * As long as the iterator's elements do not satisfy [test] they are |
232 * discarded. Once an element satisfies the [test] the iterator stops testing | 197 * discarded. Once an element satisfies the [test] the iterator stops testing |
233 * and uses every element unconditionally. | 198 * and uses every element unconditionally. |
234 */ | 199 */ |
235 Iterable<E> skipWhile(bool test(E value)) { | 200 Iterable<E> skipWhile(bool test(E value)); |
236 return new SkipWhileIterable<E>(this, test); | |
237 } | |
238 | 201 |
239 /** | 202 /** |
240 * Returns the first element. | 203 * Returns the first element. |
241 * | 204 * |
242 * If [this] is empty throws a [StateError]. Otherwise this method is | 205 * If [this] is empty throws a [StateError]. Otherwise this method is |
243 * equivalent to [:this.elementAt(0):] | 206 * equivalent to [:this.elementAt(0):] |
244 */ | 207 */ |
245 E get first { | 208 E get first; |
246 Iterator it = iterator; | |
247 if (!it.moveNext()) { | |
248 throw new StateError("No elements"); | |
249 } | |
250 return it.current; | |
251 } | |
252 | 209 |
253 /** | 210 /** |
254 * Returns the last element. | 211 * Returns the last element. |
255 * | 212 * |
256 * If [this] is empty throws a [StateError]. | 213 * If [this] is empty throws a [StateError]. |
257 */ | 214 */ |
258 E get last { | 215 E get last; |
259 Iterator it = iterator; | |
260 if (!it.moveNext()) { | |
261 throw new StateError("No elements"); | |
262 } | |
263 E result; | |
264 do { | |
265 result = it.current; | |
266 } while(it.moveNext()); | |
267 return result; | |
268 } | |
269 | 216 |
270 /** | 217 /** |
271 * Returns the single element in [this]. | 218 * Returns the single element in [this]. |
272 * | 219 * |
273 * If [this] is empty or has more than one element throws a [StateError]. | 220 * If [this] is empty or has more than one element throws a [StateError]. |
274 */ | 221 */ |
275 E get single { | 222 E get single; |
276 Iterator it = iterator; | |
277 if (!it.moveNext()) throw new StateError("No elements"); | |
278 E result = it.current; | |
279 if (it.moveNext()) throw new StateError("More than one element"); | |
280 return result; | |
281 } | |
282 | 223 |
283 /** | 224 /** |
284 * Returns the first element that satisfies the given predicate [f]. | 225 * Returns the first element that satisfies the given predicate [f]. |
285 * | 226 * |
286 * If none matches, the result of invoking the [orElse] function is | 227 * If none matches, the result of invoking the [orElse] function is |
287 * returned. By default, when [orElse] is `null`, a [StateError] is | 228 * returned. By default, when [orElse] is `null`, a [StateError] is |
288 * thrown. | 229 * thrown. |
289 */ | 230 */ |
290 E firstWhere(bool test(E value), { E orElse() }) { | 231 E firstWhere(bool test(E value), { E orElse() }); |
291 // TODO(floitsch): check that arguments are of correct type? | |
292 for (E element in this) { | |
293 if (test(element)) return element; | |
294 } | |
295 if (orElse != null) return orElse(); | |
296 throw new StateError("No matching element"); | |
297 } | |
298 | 232 |
299 /** | 233 /** |
300 * Returns the last element that satisfies the given predicate [f]. | 234 * Returns the last element that satisfies the given predicate [f]. |
301 * | 235 * |
302 * If none matches, the result of invoking the [orElse] function is | 236 * If none matches, the result of invoking the [orElse] function is |
303 * returned. By default, when [orElse] is [:null:], a [StateError] is | 237 * returned. By default, when [orElse] is [:null:], a [StateError] is |
304 * thrown. | 238 * thrown. |
305 */ | 239 */ |
306 E lastWhere(bool test(E value), {E orElse()}) { | 240 E lastWhere(bool test(E value), {E orElse()}); |
307 // TODO(floitsch): check that arguments are of correct type? | |
308 E result = null; | |
309 bool foundMatching = false; | |
310 for (E element in this) { | |
311 if (test(element)) { | |
312 result = element; | |
313 foundMatching = true; | |
314 } | |
315 } | |
316 if (foundMatching) return result; | |
317 if (orElse != null) return orElse(); | |
318 throw new StateError("No matching element"); | |
319 } | |
320 | 241 |
321 /** | 242 /** |
322 * Returns the single element that satisfies [f]. If no or more than one | 243 * Returns the single element that satisfies [f]. If no or more than one |
323 * element match then a [StateError] is thrown. | 244 * element match then a [StateError] is thrown. |
324 */ | 245 */ |
325 E singleWhere(bool test(E value)) { | 246 E singleWhere(bool test(E value)); |
326 // TODO(floitsch): check that argument is of correct type? | |
327 E result = null; | |
328 bool foundMatching = false; | |
329 for (E element in this) { | |
330 if (test(element)) { | |
331 if (foundMatching) { | |
332 throw new StateError("More than one matching element"); | |
333 } | |
334 result = element; | |
335 foundMatching = true; | |
336 } | |
337 } | |
338 if (foundMatching) return result; | |
339 throw new StateError("No matching element"); | |
340 } | |
341 | 247 |
342 /** | 248 /** |
343 * Returns the [index]th element. | 249 * Returns the [index]th element. |
344 * | 250 * |
345 * If [this] [Iterable] has fewer than [index] elements throws a | 251 * If [this] [Iterable] has fewer than [index] elements throws a |
346 * [RangeError]. | 252 * [RangeError]. |
347 * | 253 * |
348 * Note: if [this] does not have a deterministic iteration order then the | 254 * Note: if [this] does not have a deterministic iteration order then the |
349 * function may simply return any element without any iteration if there are | 255 * function may simply return any element without any iteration if there are |
350 * at least [index] elements in [this]. | 256 * at least [index] elements in [this]. |
351 */ | 257 */ |
352 E elementAt(int index) { | 258 E elementAt(int index); |
353 if (index is! int || index < 0) throw new RangeError.value(index); | |
354 int remaining = index; | |
355 for (E element in this) { | |
356 if (remaining == 0) return element; | |
357 remaining--; | |
358 } | |
359 throw new RangeError.value(index); | |
360 } | |
361 } | 259 } |
362 | 260 |
363 | 261 |
364 typedef E _Generator<E>(int index); | 262 typedef E _Generator<E>(int index); |
365 | 263 |
366 class _GeneratorIterable<E> extends Iterable<E> { | 264 class _GeneratorIterable<E> extends IterableBase<E> { |
367 final int _count; | 265 final int _count; |
368 final _Generator<E> _generator; | 266 final _Generator<E> _generator; |
369 _GeneratorIterable(this._count, this._generator); | 267 _GeneratorIterable(this._count, this._generator); |
370 Iterator<E> get iterator => new _GeneratorIterator(_count, _generator); | 268 Iterator<E> get iterator => new _GeneratorIterator(_count, _generator); |
371 } | 269 } |
372 | 270 |
373 class _GeneratorIterator<E> implements Iterator<E> { | 271 class _GeneratorIterator<E> implements Iterator<E> { |
374 final int _count; | 272 final int _count; |
375 final _Generator<E> _generator; | 273 final _Generator<E> _generator; |
376 int _index = 0; | 274 int _index = 0; |
(...skipping 11 matching lines...) Expand all Loading... |
388 return false; | 286 return false; |
389 } | 287 } |
390 } | 288 } |
391 | 289 |
392 E get current => _current; | 290 E get current => _current; |
393 } | 291 } |
394 | 292 |
395 /** | 293 /** |
396 * An [Iterator] that allows moving backwards as well as forwards. | 294 * An [Iterator] that allows moving backwards as well as forwards. |
397 */ | 295 */ |
398 abstract class BidirectionalIterator<T> extends Iterator<T> { | 296 abstract class BidirectionalIterator<E> implements Iterator<E> { |
399 /** | 297 /** |
400 * Move back to the previous element. | 298 * Move back to the previous element. |
401 * | 299 * |
402 * Returns true and updates [current] if successful. Returns false | 300 * Returns true and updates [current] if successful. Returns false |
403 * and sets [current] to null if there is no previous element. | 301 * and sets [current] to null if there is no previous element. |
404 */ | 302 */ |
405 bool movePrevious(); | 303 bool movePrevious(); |
406 } | 304 } |
OLD | NEW |