Created
November 7, 2011 18:48
-
-
Save seaneagan/1345796 to your computer and use it in GitHub Desktop.
Dart-iterable-methods
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // mixin instead of a class ? | |
| class CollectionImpl<E> implements Collection<E> { | |
| Iterable _wrapped; | |
| CollectionImpl(Iterable other) { | |
| this._wrapped = other; | |
| } | |
| Iterator<E> iterator() => _wrapped.iterator(); | |
| int get count () { | |
| final int count = 0; | |
| for(final i in this) count++; | |
| return count; | |
| } | |
| bool get empty () => !iterator().hasNext(); | |
| bool contains (E item) { | |
| for(final i in this) { | |
| if(item == i) { // i == item instead ? | |
| return true; | |
| } | |
| return false; | |
| } | |
| } | |
| bool containsIdentical (E item) { | |
| for(final i in this) { | |
| if(item === i) { | |
| return true; | |
| } | |
| return false; | |
| } | |
| } | |
| bool containsAll (Iterable<E> other) { | |
| for(final i in other) { | |
| if(!contains(i)) { | |
| return false; | |
| } | |
| return true; | |
| } | |
| } | |
| void forEach(void f(E item/*, int index, Iterable<E> self*/)) { | |
| int i = 0; | |
| for(final item in this) f(item/*, i++, this*/); | |
| } | |
| bool every(bool f(E item/*, int index, Iterable<E> self*/)) { | |
| int i = 0; | |
| for(final item in this) if(!f(item/*, i++, this*/)) return false; | |
| return true; | |
| } | |
| bool some(bool f(E item/*, int index, Iterable<E> self*/)) { | |
| int i = 0; | |
| for(final item in this) if(f(item/*, i++, this*/)) return true; | |
| return false; | |
| } | |
| void join([String separator = '']) { | |
| String joined = ''; | |
| final iter = iterator(); | |
| bool hasNext = iter.hasNext(); | |
| while(hasNext) { | |
| joined += iter.next().toString(); | |
| if(hasNext = iter.hasNext()) joined += separator; | |
| } | |
| return joined; | |
| } | |
| // Note: initialValue could be optional when E is assignable to T | |
| // Need generic functions here (see http://code.google.com/p/dart/issues/detail?id=254) | |
| /*T*/ reduce/*<T>*/(Dynamic/*T*/ f(/*T*/ previous, E current), [/*T*/ initialValue = null]) { | |
| var/*T*/ previous = initialValue; | |
| for(final item in this) previous = f(previous, current); | |
| return previous; | |
| } | |
| Iterable<E> filter(FilterCallback<E> f) => new _FilterIterable(this, f); | |
| // Need generic functions here | |
| Iterable<Dynamic/*T*/> map/*<T>*/(MapCallback<E, Dynamic/*T*/> f) => new _MapIterable(this, f); | |
| /** Compute the minimum of an iterable. Returns initialValue if empty. */ | |
| E min(Comparator<E> f, [E initialValue]) => reduce((prev, curr) => f(prev, curr) <= 0 ? prev : curr, initialValue); | |
| /** Compute the maximum of an iterable. Returns initialValue if empty. */ | |
| E max(Comparator<E> f, [E initialValue]) => reduce((prev, curr) => f(prev, curr) >= 0 ? prev : curr, initialValue); | |
| /** Orders an iterable by its values, or by a key selector. */ | |
| Iterable<E> sort(Comparator<E> comparator]) { | |
| final result = new List.from(source); | |
| sortBy(result, selector); | |
| return result; | |
| } | |
| /** Sorts a list by its values, or by a key selector. */ | |
| // TODO(jmesserly): we probably don't want to call the key selector more than | |
| // once for a given element. This would improve performance and the API | |
| // contract could be stronger. | |
| static void sortBy(List list, [NumericValueSelector selector = null]) { | |
| if (selector != null) { | |
| list.sort((x, y) => selector(x) - selector(y)); | |
| } else { | |
| list.sort((x, y) => x - y); | |
| } | |
| } | |
| /** Compute the sum of an iterable. Needs structural types to check for + operator */ | |
| E sum(E initialValue) { | |
| Addable<E> | |
| E operator + (E other); | |
| // throw error if E does not support + operator | |
| return reduce((E prev, E curr) => prev + curr, initialValue); | |
| final iter = source.iterator(); | |
| } | |
| class _FilterIterable<E> implements Iterable<E> { | |
| Iterable<E> _source; | |
| FilterCallback<E> _filter; | |
| _FilterIterable(this._source, this._filter); | |
| iterator() => new _FilterIterator(this); | |
| } | |
| class _FilterIterator<E> implements Iterator<E> { | |
| _FilterIterable<E> _iterable; | |
| Iterator<E> _iterator; | |
| E _next; | |
| bool _hasNext = true; | |
| bool _mustFindNext = true; | |
| int _index = 0; | |
| _FilterIterator(this._iterable) { | |
| _iterator = _iterable.iterator(); | |
| } | |
| E next() { | |
| _findNext(); | |
| _mustFindNext = true; | |
| if(_hasNext) { | |
| return _next; | |
| } | |
| // throw | |
| } | |
| bool hasNext() {_findNext(); return _hasNext;} | |
| _findNext() { | |
| while(_mustFindNext) { | |
| if(!_iterator.hasNext()) { | |
| _hasNext = false; | |
| _mustFindNext = false; | |
| } | |
| else if(_iterable._filter(_next = _iterator.next()/*, _index++, _iterable._source*/)) _mustFindNext = false; | |
| } | |
| } | |
| } | |
| class _MapIterable<E, T> implements Iterable<T> { | |
| Iterable<E> _source; | |
| MapCallback<E, T> _map; | |
| _MapIterable(this._source, this._map); | |
| iterator() => new _MapIterator(this); | |
| } | |
| class _MapIterator<E, T> implements Iterator<T> { | |
| _MapIterable<E, T> _iterable; | |
| Iterator<E> _iterator; | |
| int _index = 0; | |
| _MapIterator(this._iterable) { | |
| _iterator = _iterable.iterator(); | |
| } | |
| T next() => _iterable._map(_iterator.next()/*, _index++, _iterable._source*/); | |
| bool hasNext() => _iterator.hasNext(); | |
| } | |
| class _UnionIterable<E> implements Iterable<E> { | |
| final Iterable<E> _first, _second; | |
| const _UnionIterable(this._first, this._second); | |
| iterator() => new _UnionIterator(this); | |
| } | |
| class _UnionIterator<E> implements Iterator<E> { | |
| final _UnionIterable<E> _iterable; | |
| Iterator<E> _iterator; | |
| bool _inFirst = true; | |
| _UnionIterator(this._iterable) { | |
| _iterator = _iterable._first.iterator(); | |
| } | |
| E next() { | |
| _updateIterator(); | |
| if(_iterator.hasNext()) return _iterator.next(); | |
| // throw | |
| } | |
| bool hasNext() { | |
| _updateIterator(); | |
| return _iterator.hasNext(); | |
| } | |
| void _updateIterator() { | |
| if(_inFirst && !_iterator.hasNext()) { | |
| _inFirst = false; | |
| _iterator = _iterable._second.iterator(); | |
| } | |
| } | |
| typedef T MapCallback<E, T>(E item/*, int index, Iterable<E> self*/); | |
| typedef bool FilterCallback<E>(E item/*, int index, Iterable<E> self*/); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment