Skip to content

Instantly share code, notes, and snippets.

@MisterJimson
Created April 23, 2022 02:00
Show Gist options
  • Save MisterJimson/36d56c88e14b0738f01c6c467174aa35 to your computer and use it in GitHub Desktop.
Save MisterJimson/36d56c88e14b0738f01c6c467174aa35 to your computer and use it in GitHub Desktop.
CachedIterable
void main() {
final inputs = ['a', 'b', 'c', 'd', 'e', 'f'];
final map = inputs.map((e) {
print(e);
return e;
});
final cachedIterable = inputs.mapCached((e) {
print(e);
return e;
});
print("map");
map.first;
map.first;
print("cachedIterable");
cachedIterable.first;
cachedIterable.first;
}
typedef V Transformation<K, V>(K value);
class CachedIterable<S, T> extends Iterable<T> {
final Iterable<S> _iterable;
final Transformation<S, T> _f;
Map<int, T> cache = {};
factory CachedIterable(Iterable<S> iterable, T Function(S) f) {
return CachedIterable<S, T>._(iterable, f);
}
CachedIterable._(this._iterable, this._f);
@override
Iterator<T> get iterator => MappedIterator<S, T>(_iterable.iterator, _f);
@override
int get length => _iterable.length;
@override
bool get isEmpty => _iterable.isEmpty;
@override
T get first => elementAt(0);
@override
T get last => elementAt(length - 1);
@override
T get single => _f(_iterable.single);
@override
T elementAt(int index) {
if (cache.containsKey(index)) {
return cache[index]!;
} else {
final value = _f(_iterable.elementAt(index));
cache[index] = value;
return value;
}
}
}
extension CachedIterableEx<T, E> on Iterable<E> {
Iterable<T> mapCached<T>(T Function(E) func) =>
CachedIterable<E, T>(this, func);
}
class MappedIterator<S, T> extends Iterator<T> {
T? _current;
final Iterator<S> _iterator;
final Transformation<S, T> _f;
MappedIterator(this._iterator, this._f);
@override
bool moveNext() {
if (_iterator.moveNext()) {
_current = _f(_iterator.current);
return true;
}
_current = null;
return false;
}
@override
T get current => _current as T;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment