@everwhen/temporal
Version:
_description_
70 lines (69 loc) • 2.2 kB
JavaScript
/**
* A series wraps a list of values that should be
* treated with order, providing methods to navigate
* and compare items within the series.
*/
export class Series {
#items;
#indexesByKey;
#itemsByIndex;
#toKey;
constructor(items, toKey = (item) => `${item}`) {
this.#items = items;
this.#toKey = toKey;
this.#indexesByKey = new Map();
this.#itemsByIndex = new Map();
items.forEach((item, idx) => {
this.#indexesByKey.set(toKey(item), idx);
this.#itemsByIndex.set(idx, item);
});
}
/**
* Given two values in the series, returns the
* value that occurs earlier in the series
*/
min(a, b) {
const idxA = this.#indexesByKey.get(this.#toKey(a)) ?? 0;
const idxB = this.#indexesByKey.get(this.#toKey(b)) ?? 0;
return idxA < idxB ? a : b;
}
/**
* Given two values in the series, returns the
* value that occurs later in the series
*/
max(a, b) {
const idxA = this.#indexesByKey.get(this.#toKey(a)) ?? 0;
const idxB = this.#indexesByKey.get(this.#toKey(b)) ?? 0;
return idxA > idxB ? a : b;
}
/**
* Returns the first item from the series
*/
first() {
return this.#itemsByIndex.get(0);
}
/**
* Returns the last item in the series
*/
last() {
return this.#itemsByIndex.get(this.#items.length - 1);
}
/**
* Given an item in the series returns the next item
* in the series or default if the given value is
* the last item in the series
*/
next(current, defaultValue) {
const currentIdx = this.#indexesByKey.get(this.#toKey(current)) ?? -1;
return (this.#itemsByIndex.get(currentIdx + 1) ?? defaultValue ?? this.first());
}
/**
* Given an item in the series returns the previous item
* in the series or default if the given value is
* the first item in the series
*/
previous(current, defaultValue) {
const currentIdx = this.#indexesByKey.get(this.#toKey(current)) ?? 0;
return this.#itemsByIndex.get(currentIdx - 1) ?? defaultValue ?? this.last();
}
}