Skip to content

Commit

Permalink
refactor: use TreeSetView in FilteredMapView
Browse files Browse the repository at this point in the history
  • Loading branch information
rbellens committed Feb 28, 2024
1 parent 2591514 commit ac0ee98
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 44 deletions.
37 changes: 23 additions & 14 deletions lib/src/filteredmap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ class FilteredMapView<K extends Comparable, V> extends MapBase<K, V>

@override
V? operator [](Object? key) {
var k = _entryForKey(key)?.key;
return k != null ? _baseMap[k] : null;
var e = _entryForKey(key);
return e?.value;
}

@override
Expand All @@ -102,9 +102,8 @@ class FilteredMapView<K extends Comparable, V> extends MapBase<K, V>
bool _containsPair(Pair pair) => _effectiveInterval.containsPoint(pair);

KeyValueInterval get _effectiveInterval {
var keys = this.keys;
return KeyValueInterval.fromPairs(_entryForKey(keys.first, false)!.index,
_entryForKey(keys.last, false)!.index);
return KeyValueInterval.fromPairs(ordering.indexFromMapEntry(entries.first),
ordering.indexFromMapEntry(entries.last));
}

@override
Expand All @@ -125,6 +124,16 @@ class FilteredMapView<K extends Comparable, V> extends MapBase<K, V>
limit: filter.limit,
reversed: filter.reversed);

@override
Iterable<V> get values => keys.map((k) => _baseMap[k]!);

@override
Iterable<MapEntry<K, V>> get entries => _baseMap.subentries(
start: filter.validInterval.start,
end: filter.validInterval.end,
limit: filter.limit,
reversed: filter.reversed);

/// Returns true when the [completeInterval] is within the complete interval
/// of the base map.
bool get isComplete {
Expand All @@ -137,15 +146,6 @@ class FilteredMapView<K extends Comparable, V> extends MapBase<K, V>
@override
Ordering get ordering => _baseMap.ordering;

@override
Iterable<K> subkeys(
{required Pair start,
required Pair end,
int? limit,
bool reversed = false}) {
throw UnimplementedError();
}

@override
int get length {
var b = _baseMap;
Expand All @@ -161,4 +161,13 @@ class FilteredMapView<K extends Comparable, V> extends MapBase<K, V>
}
return super.length;
}

@override
Iterable<MapEntry<K, V>> subentries(
{required Pair start,
required Pair end,
int? limit,
bool reversed = false}) {
throw UnimplementedError();
}
}
47 changes: 25 additions & 22 deletions lib/src/sortedmap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,26 @@ abstract class SortedMap<K extends Comparable, V> implements Map<K, V> {

/// Gets the keys within the desired bounds and limit.
Iterable<K> subkeys(
{required Pair start,
required Pair end,
int? limit,
bool reversed = false}) =>
subentries(start: start, end: end, limit: limit, reversed: reversed)
.map((v) => v.key);

/// Gets the entries within the desired bounds and limit.
Iterable<MapEntry<K, V>> subentries(
{required Pair start,
required Pair end,
int? limit,
bool reversed = false});

@override
Iterable<K> get keys => entries.map<K>((p) => p.key);

@override
Iterable<V> get values => entries.map<V>((p) => p.value);

/// Creates a filtered view of this map.
FilteredMapView<K, V> filteredMapView(
{required Pair start,
Expand Down Expand Up @@ -169,12 +184,6 @@ class _SortedMap<K extends Comparable, V> extends MapBase<K, V>
@override
bool containsKey(Object? key) => _map.containsKey(key);

@override
Iterable<K> get keys => _sortedEntries.map<K>((p) => p.key);

@override
Iterable<V> get values => _sortedEntries.map<V>((p) => p.value);

@override
Iterable<MapEntry<K, V>> get entries => _sortedEntries;

Expand Down Expand Up @@ -268,26 +277,20 @@ class _SortedMap<K extends Comparable, V> extends MapBase<K, V>
}

@override
Iterable<K> subkeys(
Iterable<MapEntry<K, V>> subentries(
{required Pair start,
required Pair end,
int? limit,
bool reversed = false}) {
var it = _subkeys(start, end, limit, reversed);
if (reversed) return it.toList().reversed;
return it;
}

Iterable<K> _subkeys(Pair start, Pair end, int? limit, bool reversed) sync* {
var from = reversed ? end : start;
var it = _sortedEntries.fromIterator(_MapEntryWithIndex.indexOnly(from),
reversed: reversed);
var count = 0;
while (it.moveNext() && (limit == null || count++ < limit)) {
var cmp = Comparable.compare(it.current.index, reversed ? start : end);
if ((reversed && cmp < 0) || (!reversed && cmp > 0)) return;
yield it.current.key;
}
var v = TreeSetView<_MapEntryWithIndex<K, V>>(
baseMap: _sortedEntries as AvlTreeSet<_MapEntryWithIndex<K, V>>,
startAt: _MapEntryWithIndex.indexOnly(start),
startInclusive: true,
endAt: _MapEntryWithIndex.indexOnly(end),
endInclusive: true,
limit: limit,
limitFromStart: !reversed);
return v;
}
}

Expand Down
85 changes: 77 additions & 8 deletions lib/src/treeset.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ abstract class TreeSet<V> implements Set<V> {
BidirectionalIterator<V> get reverseIterator;

int indexOf(V element);

@override
TreeSet<V> toSet();

TreeSet<V> get reversed;
}

abstract class _BaseTreeSet<V> extends SetMixin<V> implements TreeSet<V> {
Expand Down Expand Up @@ -72,8 +77,68 @@ abstract class _BaseTreeSet<V> extends SetMixin<V> implements TreeSet<V> {
throw IndexError.withLength(index, length,
indexable: this, name: 'index');
}
return _avlTreeSet._root!.elementAt(index + _first!.index);
return _avlTreeSet._root!
.elementAt(index + _first!.index, null)
.node
.object;
}

@override
TreeSet<V> get reversed => ReversedTreeSet(this);
}

class ReversedTreeSet<V> extends SetMixin<V> implements TreeSet<V> {
final TreeSet<V> baseMap;

ReversedTreeSet(this.baseMap);

@override
bool add(V value) {
throw UnsupportedError('add is not supported on a ReversedTreeSet');
}

@override
bool contains(Object? element) => baseMap.contains(element);

@override
bool remove(Object? value) {
throw UnsupportedError('remove is not supported on a ReversedTreeSet');
}

@override
int indexOf(V element) {
var index = baseMap.indexOf(element);
if (index == -1) return -1;
return baseMap.length - index - 1;
}

@override
int get length => baseMap.length;

@override
V? lookup(Object? element) => baseMap.lookup(element);

@override
Comparator<V> get comparator => baseMap.comparator;

@override
BidirectionalIterator<V> fromIterator(V anchor,
{bool reversed = false, bool inclusive = true}) {
return baseMap.fromIterator(anchor,
reversed: !reversed, inclusive: inclusive);
}

@override
BidirectionalIterator<V> get iterator => baseMap.reverseIterator;

@override
BidirectionalIterator<V> get reverseIterator => baseMap.iterator;

@override
TreeSet<V> toSet() => ReversedTreeSet(baseMap.toSet());

@override
TreeSet<V> get reversed => baseMap;
}

class TreeSetView<V> extends _BaseTreeSet<V> {
Expand Down Expand Up @@ -121,7 +186,9 @@ class TreeSetView<V> extends _BaseTreeSet<V> {

if (limit != null && !limitFromStart) {
var indexFromEnd = _endIndex! - v.index;
if (indexFromEnd < limit!) return null;
if (indexFromEnd >= limit!) {
return baseMap._root!.elementAt(_endIndex! - limit! + 1, v);
}
}
return v;
}
Expand All @@ -140,7 +207,9 @@ class TreeSetView<V> extends _BaseTreeSet<V> {

if (limit != null && limitFromStart) {
var indexFromStart = v.index - _startIndex!;
if (indexFromStart < limit!) return null;
if (indexFromStart >= limit!) {
return baseMap._root!.elementAt(_startIndex! + limit! - 1, v);
}
}
return v;
}
Expand Down Expand Up @@ -219,7 +288,7 @@ class AvlTreeSet<V> extends _BaseTreeSet<V> {
throw IndexError.withLength(index, length,
indexable: this, name: 'index');
}
return _root!.elementAt(index);
return _root!.elementAt(index, null).node.object;
}

@override
Expand Down Expand Up @@ -766,15 +835,15 @@ class AvlNode<V> {
return this;
}

V elementAt(int index) {
_Path<V> elementAt(int index, _Path<V>? parent) {
var l = left?.length ?? 0;
if (index < l) {
return left!.elementAt(index);
return left!.elementAt(index, _Path(this, parent));
}
if (index == l) {
return this.object;
return _Path(this, parent);
}
return right!.elementAt(index - l - 1);
return right!.elementAt(index - l - 1, _Path(this, parent));
}
}

Expand Down

0 comments on commit ac0ee98

Please sign in to comment.