blob: 9cbdf897caabe9d6e9ba04664887b3856f1e4660 [file] [log] [blame]
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of dart.collection;
/**
* This [Iterable] mixin implements all [Iterable] members except `iterator`.
*
* All other methods are implemented in terms of `iterator`.
*/
abstract class IterableMixin<E> implements Iterable<E> {
Iterable map(f(E element)) => new MappedIterable<E, dynamic>(this, f);
Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f);
Iterable expand(Iterable f(E element)) =>
new ExpandIterable<E, dynamic>(this, f);
bool contains(Object element) {
for (E e in this) {
if (e == element) return true;
}
return false;
}
void forEach(void f(E element)) {
for (E element in this) f(element);
}
E reduce(E combine(E value, E element)) {
Iterator<E> iterator = this.iterator;
if (!iterator.moveNext()) {
throw new StateError("No elements");
}
E value = iterator.current;
while (iterator.moveNext()) {
value = combine(value, iterator.current);
}
return value;
}
dynamic fold(var initialValue,
dynamic combine(var previousValue, E element)) {
var value = initialValue;
for (E element in this) value = combine(value, element);
return value;
}
bool every(bool f(E element)) {
for (E element in this) {
if (!f(element)) return false;
}
return true;
}
String join([String separator = ""]) {
Iterator<E> iterator = this.iterator;
if (!iterator.moveNext()) return "";
StringBuffer buffer = new StringBuffer();
if (separator == null || separator == "") {
do {
buffer.write("${iterator.current}");
} while (iterator.moveNext());
} else {
buffer.write("${iterator.current}");
while (iterator.moveNext()) {
buffer.write(separator);
buffer.write("${iterator.current}");
}
}
return buffer.toString();
}
bool any(bool f(E element)) {
for (E element in this) {
if (f(element)) return true;
}
return false;
}
List<E> toList({ bool growable: true }) =>
new List<E>.from(this, growable: growable);
Set<E> toSet() => new Set<E>.from(this);
int get length {
int count = 0;
Iterator it = iterator;
while (it.moveNext()) {
count++;
}
return count;
}
bool get isEmpty => !iterator.moveNext();
bool get isNotEmpty => !isEmpty;
Iterable<E> take(int n) {
return new TakeIterable<E>(this, n);
}
Iterable<E> takeWhile(bool test(E value)) {
return new TakeWhileIterable<E>(this, test);
}
Iterable<E> skip(int n) {
return new SkipIterable<E>(this, n);
}
Iterable<E> skipWhile(bool test(E value)) {
return new SkipWhileIterable<E>(this, test);
}
E get first {
Iterator it = iterator;
if (!it.moveNext()) {
throw new StateError("No elements");
}
return it.current;
}
E get last {
Iterator it = iterator;
if (!it.moveNext()) {
throw new StateError("No elements");
}
E result;
do {
result = it.current;
} while(it.moveNext());
return result;
}
E get single {
Iterator it = iterator;
if (!it.moveNext()) throw new StateError("No elements");
E result = it.current;
if (it.moveNext()) throw new StateError("More than one element");
return result;
}
dynamic firstWhere(bool test(E value), { Object orElse() }) {
for (E element in this) {
if (test(element)) return element;
}
if (orElse != null) return orElse();
throw new StateError("No matching element");
}
dynamic lastWhere(bool test(E value), { Object orElse() }) {
E result = null;
bool foundMatching = false;
for (E element in this) {
if (test(element)) {
result = element;
foundMatching = true;
}
}
if (foundMatching) return result;
if (orElse != null) return orElse();
throw new StateError("No matching element");
}
E singleWhere(bool test(E value)) {
E result = null;
bool foundMatching = false;
for (E element in this) {
if (test(element)) {
if (foundMatching) {
throw new StateError("More than one matching element");
}
result = element;
foundMatching = true;
}
}
if (foundMatching) return result;
throw new StateError("No matching element");
}
E elementAt(int index) {
if (index is! int || index < 0) throw new RangeError.value(index);
int remaining = index;
for (E element in this) {
if (remaining == 0) return element;
remaining--;
}
throw new RangeError.value(index);
}
}
/**
* Base class for implementing [Iterable].
*
* This class implements all methods of [Iterable] except [Iterable.iterator]
* in terms of `iterator`.
*/
abstract class IterableBase<E> implements Iterable<E> {
// TODO(lrn): Base this on IterableMixin if there ever becomes a way
// to combine const constructors and mixins.
const IterableBase();
Iterable map(f(E element)) => new MappedIterable<E, dynamic>(this, f);
Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f);
Iterable expand(Iterable f(E element)) =>
new ExpandIterable<E, dynamic>(this, f);
bool contains(Object element) {
for (E e in this) {
if (e == element) return true;
}
return false;
}
void forEach(void f(E element)) {
for (E element in this) f(element);
}
E reduce(E combine(E value, E element)) {
Iterator<E> iterator = this.iterator;
if (!iterator.moveNext()) {
throw new StateError("No elements");
}
E value = iterator.current;
while (iterator.moveNext()) {
value = combine(value, iterator.current);
}
return value;
}
dynamic fold(var initialValue,
dynamic combine(var previousValue, E element)) {
var value = initialValue;
for (E element in this) value = combine(value, element);
return value;
}
bool every(bool f(E element)) {
for (E element in this) {
if (!f(element)) return false;
}
return true;
}
String join([String separator = ""]) {
Iterator<E> iterator = this.iterator;
if (!iterator.moveNext()) return "";
StringBuffer buffer = new StringBuffer();
if (separator == null || separator == "") {
do {
buffer.write("${iterator.current}");
} while (iterator.moveNext());
} else {
buffer.write("${iterator.current}");
while (iterator.moveNext()) {
buffer.write(separator);
buffer.write("${iterator.current}");
}
}
return buffer.toString();
}
bool any(bool f(E element)) {
for (E element in this) {
if (f(element)) return true;
}
return false;
}
List<E> toList({ bool growable: true }) =>
new List<E>.from(this, growable: growable);
Set<E> toSet() => new Set<E>.from(this);
int get length {
int count = 0;
Iterator it = iterator;
while (it.moveNext()) {
count++;
}
return count;
}
bool get isEmpty => !iterator.moveNext();
bool get isNotEmpty => !isEmpty;
Iterable<E> take(int n) {
return new TakeIterable<E>(this, n);
}
Iterable<E> takeWhile(bool test(E value)) {
return new TakeWhileIterable<E>(this, test);
}
Iterable<E> skip(int n) {
return new SkipIterable<E>(this, n);
}
Iterable<E> skipWhile(bool test(E value)) {
return new SkipWhileIterable<E>(this, test);
}
E get first {
Iterator it = iterator;
if (!it.moveNext()) {
throw new StateError("No elements");
}
return it.current;
}
E get last {
Iterator it = iterator;
if (!it.moveNext()) {
throw new StateError("No elements");
}
E result;
do {
result = it.current;
} while(it.moveNext());
return result;
}
E get single {
Iterator it = iterator;
if (!it.moveNext()) throw new StateError("No elements");
E result = it.current;
if (it.moveNext()) throw new StateError("More than one element");
return result;
}
dynamic firstWhere(bool test(E value), { Object orElse() }) {
for (E element in this) {
if (test(element)) return element;
}
if (orElse != null) return orElse();
throw new StateError("No matching element");
}
dynamic lastWhere(bool test(E value), { Object orElse() }) {
E result = null;
bool foundMatching = false;
for (E element in this) {
if (test(element)) {
result = element;
foundMatching = true;
}
}
if (foundMatching) return result;
if (orElse != null) return orElse();
throw new StateError("No matching element");
}
E singleWhere(bool test(E value)) {
E result = null;
bool foundMatching = false;
for (E element in this) {
if (test(element)) {
if (foundMatching) {
throw new StateError("More than one matching element");
}
result = element;
foundMatching = true;
}
}
if (foundMatching) return result;
throw new StateError("No matching element");
}
E elementAt(int index) {
if (index is! int || index < 0) throw new RangeError.value(index);
int remaining = index;
for (E element in this) {
if (remaining == 0) return element;
remaining--;
}
throw new RangeError.value(index);
}
}