OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 part of dart.collection; |
| 6 |
| 7 /** |
| 8 * This [Iterable] mixin implements all [Iterable] members except `iterator`. |
| 9 * |
| 10 * All other methods are implemented in terms of `iterator`. |
| 11 */ |
| 12 abstract class IterableMixin<E> implements Iterable<E> { |
| 13 Iterable map(f(E element)) => new MappedIterable<E, dynamic>(this, f); |
| 14 |
| 15 Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f); |
| 16 |
| 17 Iterable expand(Iterable f(E element)) => |
| 18 new ExpandIterable<E, dynamic>(this, f); |
| 19 |
| 20 bool contains(E element) { |
| 21 for (E e in this) { |
| 22 if (e == element) return true; |
| 23 } |
| 24 return false; |
| 25 } |
| 26 |
| 27 void forEach(void f(E element)) { |
| 28 for (E element in this) f(element); |
| 29 } |
| 30 |
| 31 E reduce(E combine(E value, E element)) { |
| 32 Iterator<E> iterator = this.iterator; |
| 33 if (!iterator.moveNext()) { |
| 34 throw new StateError("No elements"); |
| 35 } |
| 36 E value = iterator.current; |
| 37 while (iterator.moveNext()) { |
| 38 value = combine(value, iterator.current); |
| 39 } |
| 40 return value; |
| 41 } |
| 42 |
| 43 dynamic fold(var initialValue, |
| 44 dynamic combine(var previousValue, E element)) { |
| 45 var value = initialValue; |
| 46 for (E element in this) value = combine(value, element); |
| 47 return value; |
| 48 } |
| 49 |
| 50 bool every(bool f(E element)) { |
| 51 for (E element in this) { |
| 52 if (!f(element)) return false; |
| 53 } |
| 54 return true; |
| 55 } |
| 56 |
| 57 String join([String separator]) { |
| 58 Iterator<E> iterator = this.iterator; |
| 59 if (!iterator.moveNext()) return ""; |
| 60 StringBuffer buffer = new StringBuffer(); |
| 61 if (separator == null || separator == "") { |
| 62 do { |
| 63 buffer.write("${iterator.current}"); |
| 64 } while (iterator.moveNext()); |
| 65 } else { |
| 66 buffer.write("${iterator.current}"); |
| 67 while (iterator.moveNext()) { |
| 68 buffer.write(separator); |
| 69 buffer.write("${iterator.current}"); |
| 70 } |
| 71 } |
| 72 return buffer.toString(); |
| 73 } |
| 74 |
| 75 bool any(bool f(E element)) { |
| 76 for (E element in this) { |
| 77 if (f(element)) return true; |
| 78 } |
| 79 return false; |
| 80 } |
| 81 |
| 82 List<E> toList({ bool growable: true }) => |
| 83 new List<E>.from(this, growable: growable); |
| 84 |
| 85 Set<E> toSet() => new Set<E>.from(this); |
| 86 |
| 87 int get length { |
| 88 int count = 0; |
| 89 Iterator it = iterator; |
| 90 while (it.moveNext()) { |
| 91 count++; |
| 92 } |
| 93 return count; |
| 94 } |
| 95 |
| 96 bool get isEmpty => !iterator.moveNext(); |
| 97 |
| 98 Iterable<E> take(int n) { |
| 99 return new TakeIterable<E>(this, n); |
| 100 } |
| 101 |
| 102 Iterable<E> takeWhile(bool test(E value)) { |
| 103 return new TakeWhileIterable<E>(this, test); |
| 104 } |
| 105 |
| 106 Iterable<E> skip(int n) { |
| 107 return new SkipIterable<E>(this, n); |
| 108 } |
| 109 |
| 110 Iterable<E> skipWhile(bool test(E value)) { |
| 111 return new SkipWhileIterable<E>(this, test); |
| 112 } |
| 113 |
| 114 E get first { |
| 115 Iterator it = iterator; |
| 116 if (!it.moveNext()) { |
| 117 throw new StateError("No elements"); |
| 118 } |
| 119 return it.current; |
| 120 } |
| 121 |
| 122 E get last { |
| 123 Iterator it = iterator; |
| 124 if (!it.moveNext()) { |
| 125 throw new StateError("No elements"); |
| 126 } |
| 127 E result; |
| 128 do { |
| 129 result = it.current; |
| 130 } while(it.moveNext()); |
| 131 return result; |
| 132 } |
| 133 |
| 134 E get single { |
| 135 Iterator it = iterator; |
| 136 if (!it.moveNext()) throw new StateError("No elements"); |
| 137 E result = it.current; |
| 138 if (it.moveNext()) throw new StateError("More than one element"); |
| 139 return result; |
| 140 } |
| 141 |
| 142 E firstWhere(bool test(E value), { E orElse() }) { |
| 143 // TODO(floitsch): check that arguments are of correct type? |
| 144 for (E element in this) { |
| 145 if (test(element)) return element; |
| 146 } |
| 147 if (orElse != null) return orElse(); |
| 148 throw new StateError("No matching element"); |
| 149 } |
| 150 |
| 151 E lastWhere(bool test(E value), {E orElse()}) { |
| 152 // TODO(floitsch): check that arguments are of correct type? |
| 153 E result = null; |
| 154 bool foundMatching = false; |
| 155 for (E element in this) { |
| 156 if (test(element)) { |
| 157 result = element; |
| 158 foundMatching = true; |
| 159 } |
| 160 } |
| 161 if (foundMatching) return result; |
| 162 if (orElse != null) return orElse(); |
| 163 throw new StateError("No matching element"); |
| 164 } |
| 165 |
| 166 E singleWhere(bool test(E value)) { |
| 167 // TODO(floitsch): check that argument is of correct type? |
| 168 E result = null; |
| 169 bool foundMatching = false; |
| 170 for (E element in this) { |
| 171 if (test(element)) { |
| 172 if (foundMatching) { |
| 173 throw new StateError("More than one matching element"); |
| 174 } |
| 175 result = element; |
| 176 foundMatching = true; |
| 177 } |
| 178 } |
| 179 if (foundMatching) return result; |
| 180 throw new StateError("No matching element"); |
| 181 } |
| 182 |
| 183 E elementAt(int index) { |
| 184 if (index is! int || index < 0) throw new RangeError.value(index); |
| 185 int remaining = index; |
| 186 for (E element in this) { |
| 187 if (remaining == 0) return element; |
| 188 remaining--; |
| 189 } |
| 190 throw new RangeError.value(index); |
| 191 } |
| 192 } |
| 193 |
| 194 /** |
| 195 * Base class for implementing [Iterable]. |
| 196 * |
| 197 * This class implements all methods of [Iterable] except [Iterable.iterator] |
| 198 * in terms of `iterator`. |
| 199 */ |
| 200 abstract class IterableBase<E> implements Iterable<E> { |
| 201 // TODO(lrn): Base this on IterableMixin if there ever becomes a way |
| 202 // to combine const constructors and mixins. |
| 203 const IterableBase(); |
| 204 |
| 205 Iterable map(f(E element)) => new MappedIterable<E, dynamic>(this, f); |
| 206 |
| 207 Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f); |
| 208 |
| 209 Iterable expand(Iterable f(E element)) => |
| 210 new ExpandIterable<E, dynamic>(this, f); |
| 211 |
| 212 bool contains(E element) { |
| 213 for (E e in this) { |
| 214 if (e == element) return true; |
| 215 } |
| 216 return false; |
| 217 } |
| 218 |
| 219 void forEach(void f(E element)) { |
| 220 for (E element in this) f(element); |
| 221 } |
| 222 |
| 223 E reduce(E combine(E value, E element)) { |
| 224 Iterator<E> iterator = this.iterator; |
| 225 if (!iterator.moveNext()) { |
| 226 throw new StateError("No elements"); |
| 227 } |
| 228 E value = iterator.current; |
| 229 while (iterator.moveNext()) { |
| 230 value = combine(value, iterator.current); |
| 231 } |
| 232 return value; |
| 233 } |
| 234 |
| 235 dynamic fold(var initialValue, |
| 236 dynamic combine(var previousValue, E element)) { |
| 237 var value = initialValue; |
| 238 for (E element in this) value = combine(value, element); |
| 239 return value; |
| 240 } |
| 241 |
| 242 bool every(bool f(E element)) { |
| 243 for (E element in this) { |
| 244 if (!f(element)) return false; |
| 245 } |
| 246 return true; |
| 247 } |
| 248 |
| 249 String join([String separator]) { |
| 250 Iterator<E> iterator = this.iterator; |
| 251 if (!iterator.moveNext()) return ""; |
| 252 StringBuffer buffer = new StringBuffer(); |
| 253 if (separator == null || separator == "") { |
| 254 do { |
| 255 buffer.write("${iterator.current}"); |
| 256 } while (iterator.moveNext()); |
| 257 } else { |
| 258 buffer.write("${iterator.current}"); |
| 259 while (iterator.moveNext()) { |
| 260 buffer.write(separator); |
| 261 buffer.write("${iterator.current}"); |
| 262 } |
| 263 } |
| 264 return buffer.toString(); |
| 265 } |
| 266 |
| 267 bool any(bool f(E element)) { |
| 268 for (E element in this) { |
| 269 if (f(element)) return true; |
| 270 } |
| 271 return false; |
| 272 } |
| 273 |
| 274 List<E> toList({ bool growable: true }) => |
| 275 new List<E>.from(this, growable: growable); |
| 276 |
| 277 Set<E> toSet() => new Set<E>.from(this); |
| 278 |
| 279 int get length { |
| 280 int count = 0; |
| 281 Iterator it = iterator; |
| 282 while (it.moveNext()) { |
| 283 count++; |
| 284 } |
| 285 return count; |
| 286 } |
| 287 |
| 288 bool get isEmpty => !iterator.moveNext(); |
| 289 |
| 290 Iterable<E> take(int n) { |
| 291 return new TakeIterable<E>(this, n); |
| 292 } |
| 293 |
| 294 Iterable<E> takeWhile(bool test(E value)) { |
| 295 return new TakeWhileIterable<E>(this, test); |
| 296 } |
| 297 |
| 298 Iterable<E> skip(int n) { |
| 299 return new SkipIterable<E>(this, n); |
| 300 } |
| 301 |
| 302 Iterable<E> skipWhile(bool test(E value)) { |
| 303 return new SkipWhileIterable<E>(this, test); |
| 304 } |
| 305 |
| 306 E get first { |
| 307 Iterator it = iterator; |
| 308 if (!it.moveNext()) { |
| 309 throw new StateError("No elements"); |
| 310 } |
| 311 return it.current; |
| 312 } |
| 313 |
| 314 E get last { |
| 315 Iterator it = iterator; |
| 316 if (!it.moveNext()) { |
| 317 throw new StateError("No elements"); |
| 318 } |
| 319 E result; |
| 320 do { |
| 321 result = it.current; |
| 322 } while(it.moveNext()); |
| 323 return result; |
| 324 } |
| 325 |
| 326 E get single { |
| 327 Iterator it = iterator; |
| 328 if (!it.moveNext()) throw new StateError("No elements"); |
| 329 E result = it.current; |
| 330 if (it.moveNext()) throw new StateError("More than one element"); |
| 331 return result; |
| 332 } |
| 333 |
| 334 E firstWhere(bool test(E value), { E orElse() }) { |
| 335 // TODO(floitsch): check that arguments are of correct type? |
| 336 for (E element in this) { |
| 337 if (test(element)) return element; |
| 338 } |
| 339 if (orElse != null) return orElse(); |
| 340 throw new StateError("No matching element"); |
| 341 } |
| 342 |
| 343 E lastWhere(bool test(E value), {E orElse()}) { |
| 344 // TODO(floitsch): check that arguments are of correct type? |
| 345 E result = null; |
| 346 bool foundMatching = false; |
| 347 for (E element in this) { |
| 348 if (test(element)) { |
| 349 result = element; |
| 350 foundMatching = true; |
| 351 } |
| 352 } |
| 353 if (foundMatching) return result; |
| 354 if (orElse != null) return orElse(); |
| 355 throw new StateError("No matching element"); |
| 356 } |
| 357 |
| 358 E singleWhere(bool test(E value)) { |
| 359 // TODO(floitsch): check that argument is of correct type? |
| 360 E result = null; |
| 361 bool foundMatching = false; |
| 362 for (E element in this) { |
| 363 if (test(element)) { |
| 364 if (foundMatching) { |
| 365 throw new StateError("More than one matching element"); |
| 366 } |
| 367 result = element; |
| 368 foundMatching = true; |
| 369 } |
| 370 } |
| 371 if (foundMatching) return result; |
| 372 throw new StateError("No matching element"); |
| 373 } |
| 374 |
| 375 E elementAt(int index) { |
| 376 if (index is! int || index < 0) throw new RangeError.value(index); |
| 377 int remaining = index; |
| 378 for (E element in this) { |
| 379 if (remaining == 0) return element; |
| 380 remaining--; |
| 381 } |
| 382 throw new RangeError.value(index); |
| 383 } |
| 384 } |
OLD | NEW |