Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(364)

Side by Side Diff: sdk/lib/core/iterable.dart

Issue 14022007: Move Iterable implementation to collection. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sdk/lib/core/collection.dart ('k') | sdk/lib/core/string.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 * Reduce 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 * Reduce a collection to a single value by iteratively combining each element
floitsch 2013/04/11 14:24:57 Reduces
Lasse Reichstein Nielsen 2013/04/15 14:19:50 Done.
118 * of the collection with an existing value using the provided function. 99 * of the collection with an existing value using the provided function.
119 * Use [initialValue] as the initial value, and the function [combine] to 100 * Use [initialValue] as the initial value, and the function [combine] to
120 * create a new value from the previous one and an element. 101 * create a new value from the previous one and an element.
121 * 102 *
122 * Example of calculating the sum of an iterable: 103 * Example of calculating the sum of an iterable:
123 * 104 *
124 * iterable.fold(0, (prev, element) => prev + element); 105 * iterable.fold(0, (prev, element) => prev + element);
125 * 106 *
126 */ 107 */
127 dynamic fold(var initialValue, 108 dynamic fold(var initialValue,
128 dynamic combine(var previousValue, E element)) { 109 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 110
134 /** 111 /**
135 * Returns true if every elements of this collection satisify the 112 * Returns true if every elements of this collection satisify the
136 * predicate [f]. Returns false otherwise. 113 * predicate [f]. Returns false otherwise.
137 */ 114 */
138 bool every(bool f(E element)) { 115 bool every(bool f(E element));
139 for (E element in this) {
140 if (!f(element)) return false;
141 }
142 return true;
143 }
144 116
145 /** 117 /**
146 * Convert each element to a [String] and concatenate the strings. 118 * Convert each element to a [String] and concatenate the strings.
floitsch 2013/04/11 14:24:57 Converts ... concatenates ...
Lasse Reichstein Nielsen 2013/04/15 14:19:50 Done.
147 * 119 *
148 * Converts each element to a [String] by calling [Object.toString] on it. 120 * Converts each element to a [String] by calling [Object.toString] on it.
149 * Then concatenates the strings, optionally separated by the [separator] 121 * Then concatenates the strings, optionally separated by the [separator]
150 * string. 122 * string.
151 */ 123 */
152 String join([String separator = ""]) { 124 String join([String separator = ""]) {
153 StringBuffer buffer = new StringBuffer(); 125 StringBuffer buffer = new StringBuffer();
154 buffer.writeAll(this, separator); 126 buffer.writeAll(this, separator);
155 return buffer.toString(); 127 return buffer.toString();
156 } 128 }
157 129
158 /** 130 /**
159 * Returns true if one element of this collection satisfies the 131 * Returns true if one element of this collection satisfies the
160 * predicate [f]. Returns false otherwise. 132 * predicate [f]. Returns false otherwise.
161 */ 133 */
162 bool any(bool f(E element)) { 134 bool any(bool f(E element));
163 for (E element in this) {
164 if (f(element)) return true;
165 }
166 return false;
167 }
168 135
169 List<E> toList({ bool growable: true }) => 136 /**
170 new List<E>.from(this, growable: growable); 137 * Create a [List] containing the elements of this [Iterable].
floitsch 2013/04/11 14:24:57 Creates
Lasse Reichstein Nielsen 2013/04/15 14:19:50 Done.
171 Set<E> toSet() => new Set<E>.from(this); 138 *
139 * The elements will be in iteration order. The list is fixed-length
140 * if [growable] is false.
141 */
142 List<E> toList({ bool growable: true });
143
144 /**
145 * Create a [Set] containing the elements of this [Iterable].
floitsch 2013/04/11 14:24:57 Creates
Lasse Reichstein Nielsen 2013/04/15 14:19:50 Done.
146 */
147 Set<E> toSet();
172 148
173 /** 149 /**
174 * Returns the number of elements in [this]. 150 * Returns the number of elements in [this].
175 * 151 *
176 * Counting all elements may be involve running through all elements and can 152 * Counting all elements may be involve running through all elements and can
177 * therefore be slow. 153 * therefore be slow.
178 */ 154 */
179 int get length { 155 int get length;
180 int count = 0;
181 Iterator it = iterator;
182 while (it.moveNext()) {
183 count++;
184 }
185 return count;
186 }
187 156
188 /** 157 /**
189 * Returns true if there is no element in this collection. 158 * Returns true if there is no element in this collection.
190 */ 159 */
191 bool get isEmpty => !iterator.moveNext(); 160 bool get isEmpty;
192 161
193 /** 162 /**
194 * Returns an [Iterable] with at most [n] elements. 163 * Returns an [Iterable] with at most [n] elements.
195 * 164 *
196 * The returned [Iterable] may contain fewer than [n] elements, if [this] 165 * The returned [Iterable] may contain fewer than [n] elements, if [this]
197 * contains fewer than [n] elements. 166 * contains fewer than [n] elements.
198 */ 167 */
199 Iterable<E> take(int n) { 168 Iterable<E> take(int n);
200 return new TakeIterable<E>(this, n);
201 }
202 169
203 /** 170 /**
204 * Returns an [Iterable] that stops once [test] is not satisfied anymore. 171 * Returns an [Iterable] that stops once [test] is not satisfied anymore.
205 * 172 *
206 * The filtering happens lazily. Every new [Iterator] of the returned 173 * The filtering happens lazily. Every new [Iterator] of the returned
207 * [Iterable] will start iterating over the elements of [this]. 174 * [Iterable] will start iterating over the elements of [this].
208 * When the iterator encounters an element [:e:] that does not satisfy [test], 175 * 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 176 * it discards [:e:] and moves into the finished state. That is, it will not
210 * ask or provide any more elements. 177 * ask or provide any more elements.
211 */ 178 */
212 Iterable<E> takeWhile(bool test(E value)) { 179 Iterable<E> takeWhile(bool test(E value));
213 return new TakeWhileIterable<E>(this, test);
214 }
215 180
216 /** 181 /**
217 * Returns an [Iterable] that skips the first [n] elements. 182 * Returns an [Iterable] that skips the first [n] elements.
218 * 183 *
219 * If [this] has fewer than [n] elements, then the resulting [Iterable] will 184 * If [this] has fewer than [n] elements, then the resulting [Iterable] will
220 * be empty. 185 * be empty.
221 */ 186 */
222 Iterable<E> skip(int n) { 187 Iterable<E> skip(int n);
223 return new SkipIterable<E>(this, n);
224 }
225 188
226 /** 189 /**
227 * Returns an [Iterable] that skips elements while [test] is satisfied. 190 * Returns an [Iterable] that skips elements while [test] is satisfied.
228 * 191 *
229 * The filtering happens lazily. Every new [Iterator] of the returned 192 * The filtering happens lazily. Every new [Iterator] of the returned
230 * [Iterable] will iterate over all elements of [this]. 193 * [Iterable] will iterate over all elements of [this].
231 * As long as the iterator's elements do not satisfy [test] they are 194 * 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 195 * discarded. Once an element satisfies the [test] the iterator stops testing
233 * and uses every element unconditionally. 196 * and uses every element unconditionally.
234 */ 197 */
235 Iterable<E> skipWhile(bool test(E value)) { 198 Iterable<E> skipWhile(bool test(E value));
236 return new SkipWhileIterable<E>(this, test);
237 }
238 199
239 /** 200 /**
240 * Returns the first element. 201 * Returns the first element.
241 * 202 *
242 * If [this] is empty throws a [StateError]. Otherwise this method is 203 * If [this] is empty throws a [StateError]. Otherwise this method is
243 * equivalent to [:this.elementAt(0):] 204 * equivalent to [:this.elementAt(0):]
244 */ 205 */
245 E get first { 206 E get first;
246 Iterator it = iterator;
247 if (!it.moveNext()) {
248 throw new StateError("No elements");
249 }
250 return it.current;
251 }
252 207
253 /** 208 /**
254 * Returns the last element. 209 * Returns the last element.
255 * 210 *
256 * If [this] is empty throws a [StateError]. 211 * If [this] is empty throws a [StateError].
257 */ 212 */
258 E get last { 213 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 214
270 /** 215 /**
271 * Returns the single element in [this]. 216 * Returns the single element in [this].
272 * 217 *
273 * If [this] is empty or has more than one element throws a [StateError]. 218 * If [this] is empty or has more than one element throws a [StateError].
274 */ 219 */
275 E get single { 220 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 221
283 /** 222 /**
284 * Returns the first element that satisfies the given predicate [f]. 223 * Returns the first element that satisfies the given predicate [f].
285 * 224 *
286 * If none matches, the result of invoking the [orElse] function is 225 * If none matches, the result of invoking the [orElse] function is
287 * returned. By default, when [orElse] is `null`, a [StateError] is 226 * returned. By default, when [orElse] is `null`, a [StateError] is
288 * thrown. 227 * thrown.
289 */ 228 */
290 E firstWhere(bool test(E value), { E orElse() }) { 229 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 230
299 /** 231 /**
300 * Returns the last element that satisfies the given predicate [f]. 232 * Returns the last element that satisfies the given predicate [f].
301 * 233 *
302 * If none matches, the result of invoking the [orElse] function is 234 * If none matches, the result of invoking the [orElse] function is
303 * returned. By default, when [orElse] is [:null:], a [StateError] is 235 * returned. By default, when [orElse] is [:null:], a [StateError] is
304 * thrown. 236 * thrown.
305 */ 237 */
306 E lastWhere(bool test(E value), {E orElse()}) { 238 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 239
321 /** 240 /**
322 * Returns the single element that satisfies [f]. If no or more than one 241 * Returns the single element that satisfies [f]. If no or more than one
323 * element match then a [StateError] is thrown. 242 * element match then a [StateError] is thrown.
324 */ 243 */
325 E singleWhere(bool test(E value)) { 244 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 245
342 /** 246 /**
343 * Returns the [index]th element. 247 * Returns the [index]th element.
344 * 248 *
345 * If [this] [Iterable] has fewer than [index] elements throws a 249 * If [this] [Iterable] has fewer than [index] elements throws a
346 * [RangeError]. 250 * [RangeError].
347 * 251 *
348 * Note: if [this] does not have a deterministic iteration order then the 252 * 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 253 * function may simply return any element without any iteration if there are
350 * at least [index] elements in [this]. 254 * at least [index] elements in [this].
351 */ 255 */
352 E elementAt(int index) { 256 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 } 257 }
362 258
363 259
364 typedef E _Generator<E>(int index); 260 typedef E _Generator<E>(int index);
365 261
366 class _GeneratorIterable<E> extends Iterable<E> { 262 class _GeneratorIterable<E> extends IterableBase<E> {
367 final int _count; 263 final int _count;
368 final _Generator<E> _generator; 264 final _Generator<E> _generator;
369 _GeneratorIterable(this._count, this._generator); 265 _GeneratorIterable(this._count, this._generator);
370 Iterator<E> get iterator => new _GeneratorIterator(_count, _generator); 266 Iterator<E> get iterator => new _GeneratorIterator(_count, _generator);
371 } 267 }
372 268
373 class _GeneratorIterator<E> implements Iterator<E> { 269 class _GeneratorIterator<E> implements Iterator<E> {
374 final int _count; 270 final int _count;
375 final _Generator<E> _generator; 271 final _Generator<E> _generator;
376 int _index = 0; 272 int _index = 0;
(...skipping 11 matching lines...) Expand all
388 return false; 284 return false;
389 } 285 }
390 } 286 }
391 287
392 E get current => _current; 288 E get current => _current;
393 } 289 }
394 290
395 /** 291 /**
396 * An [Iterator] that allows moving backwards as well as forwards. 292 * An [Iterator] that allows moving backwards as well as forwards.
397 */ 293 */
398 abstract class BidirectionalIterator<T> extends Iterator<T> { 294 abstract class BidirectionalIterator<E> implements Iterator<E> {
399 /** 295 /**
400 * Move back to the previous element. 296 * Move back to the previous element.
401 * 297 *
402 * Returns true and updates [current] if successful. Returns false 298 * Returns true and updates [current] if successful. Returns false
403 * and sets [current] to null if there is no previous element. 299 * and sets [current] to null if there is no previous element.
404 */ 300 */
405 bool movePrevious(); 301 bool movePrevious();
406 } 302 }
OLDNEW
« no previous file with comments | « sdk/lib/core/collection.dart ('k') | sdk/lib/core/string.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698