forked from mystiq/hydrogen-web
Add type annotations to SortedArray
This commit is contained in:
parent
7b2e452cd5
commit
3d2c74a760
1 changed files with 27 additions and 20 deletions
|
@ -18,18 +18,22 @@ import {BaseObservableList} from "./BaseObservableList";
|
||||||
import {sortedIndex} from "../../utils/sortedIndex.js";
|
import {sortedIndex} from "../../utils/sortedIndex.js";
|
||||||
import {findAndUpdateInArray} from "./common";
|
import {findAndUpdateInArray} from "./common";
|
||||||
|
|
||||||
export class SortedArray extends BaseObservableList {
|
declare function sortedIndex<T>(array: T[], value: T, comparator: (left: T, right: T) => number): number;
|
||||||
constructor(comparator) {
|
|
||||||
|
export class SortedArray<T> extends BaseObservableList<T> {
|
||||||
|
private _comparator: (left: T, right: T) => number;
|
||||||
|
private _items: T[] = [];
|
||||||
|
|
||||||
|
constructor(comparator: (left: T, right: T) => number) {
|
||||||
super();
|
super();
|
||||||
this._comparator = comparator;
|
this._comparator = comparator;
|
||||||
this._items = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setManyUnsorted(items) {
|
setManyUnsorted(items: T[]): void {
|
||||||
this.setManySorted(items);
|
this.setManySorted(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
setManySorted(items) {
|
setManySorted(items: T[]): void {
|
||||||
// TODO: we can make this way faster by only looking up the first and last key,
|
// TODO: we can make this way faster by only looking up the first and last key,
|
||||||
// and merging whatever is inbetween with items
|
// and merging whatever is inbetween with items
|
||||||
// if items is not sorted, 💩🌀 will follow!
|
// if items is not sorted, 💩🌀 will follow!
|
||||||
|
@ -42,11 +46,11 @@ export class SortedArray extends BaseObservableList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
findAndUpdate(predicate, updater) {
|
findAndUpdate(predicate: (value: T) => boolean, updater: (value: T) => any | false): boolean {
|
||||||
return findAndUpdateInArray(predicate, this._items, this, updater);
|
return findAndUpdateInArray(predicate, this._items, this, updater);
|
||||||
}
|
}
|
||||||
|
|
||||||
getAndUpdate(item, updater, updateParams = null) {
|
getAndUpdate(item: T, updater: (existing: T, item: T) => any, updateParams: any = null): void {
|
||||||
const idx = this.indexOf(item);
|
const idx = this.indexOf(item);
|
||||||
if (idx !== -1) {
|
if (idx !== -1) {
|
||||||
const existingItem = this._items[idx];
|
const existingItem = this._items[idx];
|
||||||
|
@ -56,7 +60,7 @@ export class SortedArray extends BaseObservableList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update(item, updateParams = null) {
|
update(item: T, updateParams: any = null): void {
|
||||||
const idx = this.indexOf(item);
|
const idx = this.indexOf(item);
|
||||||
if (idx !== -1) {
|
if (idx !== -1) {
|
||||||
this._items[idx] = item;
|
this._items[idx] = item;
|
||||||
|
@ -64,7 +68,7 @@ export class SortedArray extends BaseObservableList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
indexOf(item) {
|
indexOf(item: T): number {
|
||||||
const idx = sortedIndex(this._items, item, this._comparator);
|
const idx = sortedIndex(this._items, item, this._comparator);
|
||||||
if (idx < this._items.length && this._comparator(this._items[idx], item) === 0) {
|
if (idx < this._items.length && this._comparator(this._items[idx], item) === 0) {
|
||||||
return idx;
|
return idx;
|
||||||
|
@ -73,7 +77,7 @@ export class SortedArray extends BaseObservableList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_getNext(item) {
|
_getNext(item: T): T | undefined {
|
||||||
let idx = sortedIndex(this._items, item, this._comparator);
|
let idx = sortedIndex(this._items, item, this._comparator);
|
||||||
while(idx < this._items.length && this._comparator(this._items[idx], item) <= 0) {
|
while(idx < this._items.length && this._comparator(this._items[idx], item) <= 0) {
|
||||||
idx += 1;
|
idx += 1;
|
||||||
|
@ -81,7 +85,7 @@ export class SortedArray extends BaseObservableList {
|
||||||
return this.get(idx);
|
return this.get(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
set(item, updateParams = null) {
|
set(item: T, updateParams: any = null): void {
|
||||||
const idx = sortedIndex(this._items, item, this._comparator);
|
const idx = sortedIndex(this._items, item, this._comparator);
|
||||||
if (idx >= this._items.length || this._comparator(this._items[idx], item) !== 0) {
|
if (idx >= this._items.length || this._comparator(this._items[idx], item) !== 0) {
|
||||||
this._items.splice(idx, 0, item);
|
this._items.splice(idx, 0, item);
|
||||||
|
@ -92,21 +96,21 @@ export class SortedArray extends BaseObservableList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get(idx) {
|
get(idx: number): T | undefined {
|
||||||
return this._items[idx];
|
return this._items[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(idx) {
|
remove(idx: number): void {
|
||||||
const item = this._items[idx];
|
const item = this._items[idx];
|
||||||
this._items.splice(idx, 1);
|
this._items.splice(idx, 1);
|
||||||
this.emitRemove(idx, item);
|
this.emitRemove(idx, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
get array() {
|
get array(): T[] {
|
||||||
return this._items;
|
return this._items;
|
||||||
}
|
}
|
||||||
|
|
||||||
get length() {
|
get length(): number {
|
||||||
return this._items.length;
|
return this._items.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,8 +120,11 @@ export class SortedArray extends BaseObservableList {
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterator that works even if the current value is removed while iterating
|
// iterator that works even if the current value is removed while iterating
|
||||||
class Iterator {
|
class Iterator<T> {
|
||||||
constructor(sortedArray) {
|
private _sortedArray: SortedArray<T> | null
|
||||||
|
private _current: T | null | undefined
|
||||||
|
|
||||||
|
constructor(sortedArray: SortedArray<T>) {
|
||||||
this._sortedArray = sortedArray;
|
this._sortedArray = sortedArray;
|
||||||
this._current = null;
|
this._current = null;
|
||||||
}
|
}
|
||||||
|
@ -145,7 +152,7 @@ class Iterator {
|
||||||
export function tests() {
|
export function tests() {
|
||||||
return {
|
return {
|
||||||
"setManyUnsorted": assert => {
|
"setManyUnsorted": assert => {
|
||||||
const sa = new SortedArray((a, b) => a.localeCompare(b));
|
const sa = new SortedArray<string>((a, b) => a.localeCompare(b));
|
||||||
sa.setManyUnsorted(["b", "a", "c"]);
|
sa.setManyUnsorted(["b", "a", "c"]);
|
||||||
assert.equal(sa.length, 3);
|
assert.equal(sa.length, 3);
|
||||||
assert.equal(sa.get(0), "a");
|
assert.equal(sa.get(0), "a");
|
||||||
|
@ -153,7 +160,7 @@ export function tests() {
|
||||||
assert.equal(sa.get(2), "c");
|
assert.equal(sa.get(2), "c");
|
||||||
},
|
},
|
||||||
"_getNext": assert => {
|
"_getNext": assert => {
|
||||||
const sa = new SortedArray((a, b) => a.localeCompare(b));
|
const sa = new SortedArray<string>((a, b) => a.localeCompare(b));
|
||||||
sa.setManyUnsorted(["b", "a", "f"]);
|
sa.setManyUnsorted(["b", "a", "f"]);
|
||||||
assert.equal(sa._getNext("a"), "b");
|
assert.equal(sa._getNext("a"), "b");
|
||||||
assert.equal(sa._getNext("b"), "f");
|
assert.equal(sa._getNext("b"), "f");
|
||||||
|
@ -162,7 +169,7 @@ export function tests() {
|
||||||
assert.equal(sa._getNext("f"), undefined);
|
assert.equal(sa._getNext("f"), undefined);
|
||||||
},
|
},
|
||||||
"iterator with removals": assert => {
|
"iterator with removals": assert => {
|
||||||
const queue = new SortedArray((a, b) => a.idx - b.idx);
|
const queue = new SortedArray<{idx: number}>((a, b) => a.idx - b.idx);
|
||||||
queue.setManyUnsorted([{idx: 5}, {idx: 3}, {idx: 1}, {idx: 4}, {idx: 2}]);
|
queue.setManyUnsorted([{idx: 5}, {idx: 3}, {idx: 1}, {idx: 4}, {idx: 2}]);
|
||||||
const it = queue[Symbol.iterator]();
|
const it = queue[Symbol.iterator]();
|
||||||
assert.equal(it.next().value.idx, 1);
|
assert.equal(it.next().value.idx, 1);
|
||||||
|
|
Loading…
Reference in a new issue