max-priority-queue-typed 2.4.0 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/types/data-structures/base/linear-base.d.ts +6 -6
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +6 -6
- package/dist/types/data-structures/binary-tree/bst.d.ts +2 -1
- package/dist/types/data-structures/binary-tree/index.d.ts +3 -3
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +150 -20
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +188 -0
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +238 -147
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +270 -0
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +181 -0
- package/dist/types/interfaces/binary-tree.d.ts +2 -2
- package/dist/types/types/data-structures/binary-tree/index.d.ts +3 -3
- package/dist/types/types/data-structures/binary-tree/tree-map.d.ts +33 -0
- package/dist/types/types/data-structures/binary-tree/tree-multi-set.d.ts +16 -0
- package/dist/types/types/data-structures/binary-tree/tree-set.d.ts +33 -0
- package/package.json +2 -2
- package/src/data-structures/base/linear-base.ts +2 -12
- package/src/data-structures/binary-tree/avl-tree.ts +1 -1
- package/src/data-structures/binary-tree/binary-tree.ts +45 -21
- package/src/data-structures/binary-tree/bst.ts +85 -10
- package/src/data-structures/binary-tree/index.ts +3 -3
- package/src/data-structures/binary-tree/red-black-tree.ts +568 -76
- package/src/data-structures/binary-tree/tree-map.ts +439 -0
- package/src/data-structures/binary-tree/tree-multi-map.ts +488 -325
- package/src/data-structures/binary-tree/tree-multi-set.ts +502 -0
- package/src/data-structures/binary-tree/tree-set.ts +407 -0
- package/src/data-structures/queue/deque.ts +10 -0
- package/src/interfaces/binary-tree.ts +2 -2
- package/src/types/data-structures/binary-tree/index.ts +3 -3
- package/src/types/data-structures/binary-tree/tree-map.ts +45 -0
- package/src/types/data-structures/binary-tree/tree-multi-set.ts +19 -0
- package/src/types/data-structures/binary-tree/tree-set.ts +39 -0
- package/dist/types/data-structures/binary-tree/avl-tree-counter.d.ts +0 -236
- package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +0 -197
- package/dist/types/data-structures/binary-tree/tree-counter.d.ts +0 -243
- package/dist/types/types/data-structures/binary-tree/avl-tree-counter.d.ts +0 -2
- package/dist/types/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +0 -2
- package/dist/types/types/data-structures/binary-tree/tree-counter.d.ts +0 -2
- package/src/data-structures/binary-tree/avl-tree-counter.ts +0 -539
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +0 -438
- package/src/data-structures/binary-tree/tree-counter.ts +0 -575
- package/src/types/data-structures/binary-tree/avl-tree-counter.ts +0 -3
- package/src/types/data-structures/binary-tree/avl-tree-multi-map.ts +0 -3
- package/src/types/data-structures/binary-tree/tree-counter.ts +0 -3
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TreeMap (ordered map) — a restricted, native-like API backed by RedBlackTree.
|
|
3
|
+
*
|
|
4
|
+
* Design goals:
|
|
5
|
+
* - No node exposure (no node inputs/outputs)
|
|
6
|
+
* - Native Map-like surface + Java NavigableMap-like helpers
|
|
7
|
+
* - Strict default comparator (number/string/Date), otherwise require comparator
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { Comparator } from '../../types';
|
|
11
|
+
import type { TreeMapEntryCallback, TreeMapOptions, TreeMapRangeOptions, TreeMapReduceCallback } from '../../types';
|
|
12
|
+
import { RedBlackTree } from './red-black-tree';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* An ordered Map backed by a red-black tree.
|
|
16
|
+
*
|
|
17
|
+
* - Iteration order is ascending by key.
|
|
18
|
+
* - No node exposure: all APIs use keys/values only.
|
|
19
|
+
*/
|
|
20
|
+
export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | undefined]> {
|
|
21
|
+
readonly #core: RedBlackTree<K, V>;
|
|
22
|
+
readonly #isDefaultComparator: boolean;
|
|
23
|
+
readonly #userComparator?: Comparator<K>;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Create a TreeMap from an iterable of `[key, value]` entries or raw elements.
|
|
27
|
+
*
|
|
28
|
+
* @param entries - Iterable of `[key, value]` tuples, or raw elements if `toEntryFn` is provided.
|
|
29
|
+
* @param options - Configuration options including optional `toEntryFn` to transform raw elements.
|
|
30
|
+
* @throws {TypeError} If any entry is not a 2-tuple-like value (when no toEntryFn), or when using
|
|
31
|
+
* the default comparator and encountering unsupported/invalid keys (e.g. `NaN`, invalid `Date`).
|
|
32
|
+
* @example
|
|
33
|
+
* // Standard usage with entries
|
|
34
|
+
* const map = new TreeMap([['a', 1], ['b', 2]]);
|
|
35
|
+
*
|
|
36
|
+
* // Using toEntryFn to transform raw objects
|
|
37
|
+
* const users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
|
|
38
|
+
* const map = new TreeMap<number, User, User>(users, { toEntryFn: u => [u.id, u] });
|
|
39
|
+
*/
|
|
40
|
+
constructor(
|
|
41
|
+
entries: Iterable<R> | Iterable<[K, V | undefined]> = [],
|
|
42
|
+
options: TreeMapOptions<K, V, R> = {}
|
|
43
|
+
) {
|
|
44
|
+
this.#userComparator = options.comparator;
|
|
45
|
+
const toEntryFn = options.toEntryFn;
|
|
46
|
+
const comparator = options.comparator ?? TreeMap.createDefaultComparator<K>();
|
|
47
|
+
this.#isDefaultComparator = options.comparator === undefined;
|
|
48
|
+
|
|
49
|
+
this.#core = new RedBlackTree<K, V>([], { comparator, isMapMode: options.isMapMode });
|
|
50
|
+
|
|
51
|
+
for (const item of entries) {
|
|
52
|
+
let k: K;
|
|
53
|
+
let v: V | undefined;
|
|
54
|
+
|
|
55
|
+
if (toEntryFn) {
|
|
56
|
+
// Use toEntryFn to transform raw element
|
|
57
|
+
[k, v] = toEntryFn(item as R);
|
|
58
|
+
} else {
|
|
59
|
+
// Validate entries like native Map: each item must be a 2-tuple-like value.
|
|
60
|
+
if (!Array.isArray(item) || item.length < 2) {
|
|
61
|
+
throw new TypeError('TreeMap: each entry must be a [key, value] tuple');
|
|
62
|
+
}
|
|
63
|
+
k = item[0] as K;
|
|
64
|
+
v = item[1] as V | undefined;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
this.set(k, v);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Create the strict default comparator.
|
|
73
|
+
*
|
|
74
|
+
* Supports:
|
|
75
|
+
* - `number` (rejects `NaN`; treats `-0` and `0` as equal)
|
|
76
|
+
* - `string`
|
|
77
|
+
* - `Date` (orders by `getTime()`, rejects invalid dates)
|
|
78
|
+
*
|
|
79
|
+
* For other key types, a custom comparator must be provided.
|
|
80
|
+
*/
|
|
81
|
+
static createDefaultComparator<K>(): Comparator<K> {
|
|
82
|
+
return (a: K, b: K): number => {
|
|
83
|
+
if (typeof a === 'number' && typeof b === 'number') {
|
|
84
|
+
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError('TreeMap: NaN is not a valid key');
|
|
85
|
+
const aa = Object.is(a, -0) ? 0 : a;
|
|
86
|
+
const bb = Object.is(b, -0) ? 0 : b;
|
|
87
|
+
return aa > bb ? 1 : aa < bb ? -1 : 0;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (typeof a === 'string' && typeof b === 'string') {
|
|
91
|
+
return a > b ? 1 : a < b ? -1 : 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (a instanceof Date && b instanceof Date) {
|
|
95
|
+
const ta = a.getTime();
|
|
96
|
+
const tb = b.getTime();
|
|
97
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError('TreeMap: invalid Date key');
|
|
98
|
+
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
throw new TypeError('TreeMap: comparator is required for non-number/non-string/non-Date keys');
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private _validateKey(key: K): void {
|
|
106
|
+
if (!this.#isDefaultComparator) return;
|
|
107
|
+
|
|
108
|
+
if (typeof key === 'number') {
|
|
109
|
+
if (Number.isNaN(key)) throw new TypeError('TreeMap: NaN is not a valid key');
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (typeof key === 'string') return;
|
|
114
|
+
|
|
115
|
+
if (key instanceof Date) {
|
|
116
|
+
if (Number.isNaN(key.getTime())) throw new TypeError('TreeMap: invalid Date key');
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
throw new TypeError('TreeMap: comparator is required for non-number/non-string/non-Date keys');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Number of entries in the map.
|
|
125
|
+
*/
|
|
126
|
+
get size(): number {
|
|
127
|
+
return this.#core.size;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Whether the map is empty.
|
|
132
|
+
*/
|
|
133
|
+
isEmpty(): boolean {
|
|
134
|
+
return this.size === 0;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Set or overwrite a value for a key.
|
|
139
|
+
* @remarks Expected time O(log n)
|
|
140
|
+
*/
|
|
141
|
+
set(key: K, value: V | undefined): this {
|
|
142
|
+
this._validateKey(key);
|
|
143
|
+
this.#core.set(key, value as V);
|
|
144
|
+
return this;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Get the value under a key.
|
|
149
|
+
* @remarks Expected time O(log n)
|
|
150
|
+
*/
|
|
151
|
+
get(key: K): V | undefined {
|
|
152
|
+
this._validateKey(key);
|
|
153
|
+
return this.#core.get(key);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Test whether a key exists.
|
|
158
|
+
* @remarks Expected time O(log n)
|
|
159
|
+
*/
|
|
160
|
+
has(key: K): boolean {
|
|
161
|
+
this._validateKey(key);
|
|
162
|
+
return this.#core.has(key);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Delete a key.
|
|
167
|
+
* @returns `true` if the key existed; otherwise `false`.
|
|
168
|
+
* @remarks Expected time O(log n)
|
|
169
|
+
*/
|
|
170
|
+
delete(key: K): boolean {
|
|
171
|
+
this._validateKey(key);
|
|
172
|
+
const res = this.#core.delete(key);
|
|
173
|
+
return Array.isArray(res) && res.length > 0 && !!res[0]?.deleted;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Remove all entries.
|
|
178
|
+
*/
|
|
179
|
+
clear(): void {
|
|
180
|
+
this.#core.clear();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Iterate over keys in ascending order.
|
|
185
|
+
*/
|
|
186
|
+
keys(): IterableIterator<K> {
|
|
187
|
+
return this.#core.keys();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private _entryFromKey(k: K): [K, V | undefined] {
|
|
191
|
+
// Keys come from `keys()` which only yields existing keys.
|
|
192
|
+
// We allow `undefined` as a stored value (native Map behavior), so entries are typed as `[K, V | undefined]`.
|
|
193
|
+
return [k, this.#core.get(k)];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Iterate over values in ascending key order.
|
|
198
|
+
*
|
|
199
|
+
* Note: values may be `undefined` (TreeMap allows storing `undefined`, like native `Map`).
|
|
200
|
+
*/
|
|
201
|
+
*values(): IterableIterator<V | undefined> {
|
|
202
|
+
for (const k of this.keys()) yield this._entryFromKey(k)[1];
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Iterate over `[key, value]` entries in ascending key order.
|
|
207
|
+
*
|
|
208
|
+
* Note: values may be `undefined`.
|
|
209
|
+
*/
|
|
210
|
+
*entries(): IterableIterator<[K, V | undefined]> {
|
|
211
|
+
for (const k of this.keys()) yield this._entryFromKey(k);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
[Symbol.iterator](): IterableIterator<[K, V | undefined]> {
|
|
215
|
+
return this.entries();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Visit each entry in ascending key order.
|
|
220
|
+
*
|
|
221
|
+
* Note: callback value may be `undefined`.
|
|
222
|
+
*/
|
|
223
|
+
forEach(cb: (value: V | undefined, key: K, map: TreeMap<K, V>) => void, thisArg?: any): void {
|
|
224
|
+
for (const [k, v] of this) cb.call(thisArg, v, k, this);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Create a new TreeMap by mapping each entry to a new `[key, value]` entry.
|
|
229
|
+
*
|
|
230
|
+
* This mirrors `RedBlackTree.map`: mapping produces a new ordered container.
|
|
231
|
+
* @remarks Time O(n log n) expected, Space O(n)
|
|
232
|
+
*/
|
|
233
|
+
map<MK, MV>(
|
|
234
|
+
callbackfn: TreeMapEntryCallback<K, V, [MK, MV], TreeMap<K, V>>,
|
|
235
|
+
options: Omit<TreeMapOptions<MK, MV>, 'toEntryFn'> & { comparator?: (a: MK, b: MK) => number } = {},
|
|
236
|
+
thisArg?: unknown
|
|
237
|
+
): TreeMap<MK, MV> {
|
|
238
|
+
const out = new TreeMap<MK, MV>([], options as TreeMapOptions<MK, MV>);
|
|
239
|
+
let index = 0;
|
|
240
|
+
for (const [k, v] of this) {
|
|
241
|
+
const [mk, mv] = thisArg === undefined
|
|
242
|
+
? callbackfn(v, k, index++, this)
|
|
243
|
+
: (callbackfn as (this: unknown, v: V | undefined, k: K, i: number, self: TreeMap<K, V>) => [MK, MV]).call(thisArg, v, k, index++, this);
|
|
244
|
+
out.set(mk, mv);
|
|
245
|
+
}
|
|
246
|
+
return out;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Create a new TreeMap containing only entries that satisfy the predicate.
|
|
251
|
+
* @remarks Time O(n log n) expected, Space O(n)
|
|
252
|
+
*/
|
|
253
|
+
filter(callbackfn: TreeMapEntryCallback<K, V, boolean, TreeMap<K, V>>, thisArg?: unknown): TreeMap<K, V> {
|
|
254
|
+
const out = new TreeMap<K, V>([], { comparator: this.#userComparator });
|
|
255
|
+
let index = 0;
|
|
256
|
+
for (const [k, v] of this) {
|
|
257
|
+
const ok = thisArg === undefined
|
|
258
|
+
? callbackfn(v, k, index++, this)
|
|
259
|
+
: (callbackfn as (this: unknown, v: V | undefined, k: K, i: number, self: TreeMap<K, V>) => boolean).call(thisArg, v, k, index++, this);
|
|
260
|
+
if (ok) out.set(k, v);
|
|
261
|
+
}
|
|
262
|
+
return out;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Reduce entries into a single accumulator.
|
|
267
|
+
* @remarks Time O(n), Space O(1)
|
|
268
|
+
*/
|
|
269
|
+
reduce<A>(callbackfn: TreeMapReduceCallback<K, V, A, TreeMap<K, V>>, initialValue: A): A {
|
|
270
|
+
let acc = initialValue;
|
|
271
|
+
let index = 0;
|
|
272
|
+
for (const [k, v] of this) acc = callbackfn(acc, v, k, index++, this);
|
|
273
|
+
return acc;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Test whether all entries satisfy a predicate.
|
|
278
|
+
* @remarks Time O(n), Space O(1)
|
|
279
|
+
*/
|
|
280
|
+
every(callbackfn: TreeMapEntryCallback<K, V, boolean, TreeMap<K, V>>, thisArg?: unknown): boolean {
|
|
281
|
+
let index = 0;
|
|
282
|
+
for (const [k, v] of this) {
|
|
283
|
+
const ok = thisArg === undefined
|
|
284
|
+
? callbackfn(v, k, index++, this)
|
|
285
|
+
: (callbackfn as (this: unknown, v: V | undefined, k: K, i: number, self: TreeMap<K, V>) => boolean).call(thisArg, v, k, index++, this);
|
|
286
|
+
if (!ok) return false;
|
|
287
|
+
}
|
|
288
|
+
return true;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Test whether any entry satisfies a predicate.
|
|
293
|
+
* @remarks Time O(n), Space O(1)
|
|
294
|
+
*/
|
|
295
|
+
some(callbackfn: TreeMapEntryCallback<K, V, boolean, TreeMap<K, V>>, thisArg?: unknown): boolean {
|
|
296
|
+
let index = 0;
|
|
297
|
+
for (const [k, v] of this) {
|
|
298
|
+
const ok = thisArg === undefined
|
|
299
|
+
? callbackfn(v, k, index++, this)
|
|
300
|
+
: (callbackfn as (this: unknown, v: V | undefined, k: K, i: number, self: TreeMap<K, V>) => boolean).call(thisArg, v, k, index++, this);
|
|
301
|
+
if (ok) return true;
|
|
302
|
+
}
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Find the first entry that satisfies a predicate.
|
|
308
|
+
* @returns The first matching `[key, value]` tuple, or `undefined`.
|
|
309
|
+
* @remarks Time O(n), Space O(1)
|
|
310
|
+
*/
|
|
311
|
+
find(callbackfn: TreeMapEntryCallback<K, V, boolean, TreeMap<K, V>>, thisArg?: unknown): [K, V | undefined] | undefined {
|
|
312
|
+
let index = 0;
|
|
313
|
+
for (const [k, v] of this) {
|
|
314
|
+
const ok = thisArg === undefined
|
|
315
|
+
? callbackfn(v, k, index++, this)
|
|
316
|
+
: (callbackfn as (this: unknown, v: V | undefined, k: K, i: number, self: TreeMap<K, V>) => boolean).call(thisArg, v, k, index++, this);
|
|
317
|
+
if (ok) return [k, v];
|
|
318
|
+
}
|
|
319
|
+
return undefined;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Materialize the map into an array of `[key, value]` tuples.
|
|
324
|
+
* @remarks Time O(n), Space O(n)
|
|
325
|
+
*/
|
|
326
|
+
toArray(): Array<[K, V | undefined]> {
|
|
327
|
+
return [...this];
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Print a human-friendly representation.
|
|
332
|
+
* @remarks Time O(n), Space O(n)
|
|
333
|
+
*/
|
|
334
|
+
print(): void {
|
|
335
|
+
// Delegate to the underlying tree's visualization.
|
|
336
|
+
this.#core.print();
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Navigable operations (return entry tuples)
|
|
340
|
+
// Note: returned tuple values may be `undefined`.
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Smallest entry by key.
|
|
344
|
+
*/
|
|
345
|
+
first(): [K, V | undefined] | undefined {
|
|
346
|
+
const k = this.#core.getLeftMost();
|
|
347
|
+
return k === undefined ? undefined : this._entryFromKey(k);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Largest entry by key.
|
|
352
|
+
*/
|
|
353
|
+
last(): [K, V | undefined] | undefined {
|
|
354
|
+
const k = this.#core.getRightMost();
|
|
355
|
+
return k === undefined ? undefined : this._entryFromKey(k);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Remove and return the smallest entry.
|
|
360
|
+
*/
|
|
361
|
+
pollFirst(): [K, V | undefined] | undefined {
|
|
362
|
+
const entry = this.first();
|
|
363
|
+
if (!entry) return undefined;
|
|
364
|
+
this.delete(entry[0]);
|
|
365
|
+
return entry;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Remove and return the largest entry.
|
|
370
|
+
*/
|
|
371
|
+
pollLast(): [K, V | undefined] | undefined {
|
|
372
|
+
const entry = this.last();
|
|
373
|
+
if (!entry) return undefined;
|
|
374
|
+
this.delete(entry[0]);
|
|
375
|
+
return entry;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Smallest entry whose key is >= the given key.
|
|
380
|
+
*/
|
|
381
|
+
ceiling(key: K): [K, V | undefined] | undefined {
|
|
382
|
+
this._validateKey(key);
|
|
383
|
+
const k = this.#core.ceiling(key);
|
|
384
|
+
return k === undefined ? undefined : this._entryFromKey(k);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Largest entry whose key is <= the given key.
|
|
389
|
+
*/
|
|
390
|
+
floor(key: K): [K, V | undefined] | undefined {
|
|
391
|
+
this._validateKey(key);
|
|
392
|
+
const k = this.#core.floor(key);
|
|
393
|
+
return k === undefined ? undefined : this._entryFromKey(k);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Smallest entry whose key is > the given key.
|
|
398
|
+
*/
|
|
399
|
+
higher(key: K): [K, V | undefined] | undefined {
|
|
400
|
+
this._validateKey(key);
|
|
401
|
+
const k = this.#core.higher(key);
|
|
402
|
+
return k === undefined ? undefined : this._entryFromKey(k);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Largest entry whose key is < the given key.
|
|
407
|
+
*/
|
|
408
|
+
lower(key: K): [K, V | undefined] | undefined {
|
|
409
|
+
this._validateKey(key);
|
|
410
|
+
const k = this.#core.lower(key);
|
|
411
|
+
return k === undefined ? undefined : this._entryFromKey(k);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Return all entries in a given key range.
|
|
416
|
+
*
|
|
417
|
+
* @param range `[low, high]`
|
|
418
|
+
* @param options Inclusive/exclusive bounds (defaults to inclusive).
|
|
419
|
+
*/
|
|
420
|
+
rangeSearch(range: [K, K], options: TreeMapRangeOptions = {}): Array<[K, V | undefined]> {
|
|
421
|
+
const { lowInclusive = true, highInclusive = true } = options;
|
|
422
|
+
const [low, high] = range;
|
|
423
|
+
this._validateKey(low);
|
|
424
|
+
this._validateKey(high);
|
|
425
|
+
|
|
426
|
+
const keys = this.#core.rangeSearch([low, high]) as (K | undefined)[];
|
|
427
|
+
const out: Array<[K, V | undefined]> = [];
|
|
428
|
+
const cmp = this.#core.comparator;
|
|
429
|
+
|
|
430
|
+
for (const k of keys) {
|
|
431
|
+
if (k === undefined) continue;
|
|
432
|
+
if (!lowInclusive && cmp(k, low) === 0) continue;
|
|
433
|
+
if (!highInclusive && cmp(k, high) === 0) continue;
|
|
434
|
+
out.push(this._entryFromKey(k));
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
return out;
|
|
438
|
+
}
|
|
439
|
+
}
|