dubc-ds-tmap 1.0.1 → 1.0.2
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/README.md +12 -2
- package/dist/index.d.ts +7 -5
- package/dist/index.js +61 -26
- package/package.json +8 -7
package/README.md
CHANGED
|
@@ -149,7 +149,7 @@ Returns an iterable iterator over the keys in the map.
|
|
|
149
149
|
|
|
150
150
|
### `.range(start:K, end:K, include?:Include)` O(1)
|
|
151
151
|
|
|
152
|
-
Returns an iterable
|
|
152
|
+
Returns an iterable over a range of keys in the map. The
|
|
153
153
|
iterator will produce key/value pairs.
|
|
154
154
|
|
|
155
155
|
The optional third parameter specifies whether the range is inclusive
|
|
@@ -197,6 +197,15 @@ The provided pairs can be in one of the three forms accepted by
|
|
|
197
197
|
`TMap`'s constructor (objects with key and value fields, tuples of
|
|
198
198
|
keys and values, or, for string keys, a JavaScript object.)
|
|
199
199
|
|
|
200
|
+
### `.slice(start:number, end:number)`
|
|
201
|
+
|
|
202
|
+
Returns an iterable over a range of indices. `end` is always exclusive.
|
|
203
|
+
|
|
204
|
+
### `.to(k:K)` O(log n)
|
|
205
|
+
|
|
206
|
+
Returns the key/value pair whose key is less than or equal to the provided
|
|
207
|
+
key, or `undefined` if no such pair exists in the map.
|
|
208
|
+
|
|
200
209
|
### `.unhear(n:number)` O(1)
|
|
201
210
|
|
|
202
211
|
Removes the listener registered with the specified number.
|
|
@@ -217,8 +226,9 @@ Returns an iterable iterator over the values in the map.
|
|
|
217
226
|
* `TMap` itself is an iterable, so you can use it directly in `for...of`
|
|
218
227
|
* `i` to get an iterator
|
|
219
228
|
* `keys()` if you just want the keys
|
|
220
|
-
* `range(start,end,include)` for partial iteration
|
|
229
|
+
* `range(start,end,include)` for partial iteration over a range of keys
|
|
221
230
|
* `reversed()` to iterate backwards
|
|
231
|
+
* `slice(start,end)` for partial iteration over a range of indices
|
|
222
232
|
* `values()` if you just want the values
|
|
223
233
|
|
|
224
234
|
### Keys
|
package/dist/index.d.ts
CHANGED
|
@@ -42,6 +42,7 @@ export interface Conf<K extends {}, V> {
|
|
|
42
42
|
readonly valueEq: (a: V, b: V) => boolean;
|
|
43
43
|
}
|
|
44
44
|
export declare class TMap<K extends {}, V> extends Base<Pair<K, V>> {
|
|
45
|
+
#private;
|
|
45
46
|
private root;
|
|
46
47
|
private _compare;
|
|
47
48
|
protected conf: Conf<K, V>;
|
|
@@ -50,7 +51,7 @@ export declare class TMap<K extends {}, V> extends Base<Pair<K, V>> {
|
|
|
50
51
|
toEmpty(): TMap<K, V>;
|
|
51
52
|
get size(): number;
|
|
52
53
|
clear(): void;
|
|
53
|
-
replace(i: Pairs<K, V>):
|
|
54
|
+
replace(i: Pairs<K, V>): boolean;
|
|
54
55
|
drop(f: (pair: Pair<K, V>) => boolean): number;
|
|
55
56
|
get compare(): (a: K, b: K) => number;
|
|
56
57
|
set compare(cmp: (a: K, b: K) => number);
|
|
@@ -59,10 +60,11 @@ export declare class TMap<K extends {}, V> extends Base<Pair<K, V>> {
|
|
|
59
60
|
get first(): Pair<K, V> | undefined;
|
|
60
61
|
get last(): Pair<K, V> | undefined;
|
|
61
62
|
[Symbol.iterator](): Generator<Pair<K, V>>;
|
|
62
|
-
keys():
|
|
63
|
-
values():
|
|
64
|
-
reversed():
|
|
65
|
-
range(startKey: K, endKey: K, inc?: Include):
|
|
63
|
+
keys(): Iterable<K>;
|
|
64
|
+
values(): Iterable<V>;
|
|
65
|
+
reversed(): Iterable<Pair<K, V>>;
|
|
66
|
+
range(startKey: K, endKey: K, inc?: Include): Iterable<Pair<K, V>>;
|
|
67
|
+
slice(start: number, end: number): Iterable<Pair<K, V>>;
|
|
66
68
|
private find;
|
|
67
69
|
get(key: K): V | undefined;
|
|
68
70
|
has(key: K): boolean;
|
package/dist/index.js
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import { Base } from "dubc-ds-base";
|
|
2
|
+
import { iterable } from "dubc-ds-iterables";
|
|
2
3
|
import { forEach } from "dubc-ds-pairs";
|
|
3
4
|
export const IN_IN = { start: true, end: true };
|
|
4
5
|
export const IN_EX = { start: true, end: false };
|
|
5
6
|
export const EX_IN = { start: false, end: true };
|
|
6
7
|
export const EX_EX = { start: false, end: false };
|
|
7
8
|
class Node {
|
|
9
|
+
key;
|
|
10
|
+
value;
|
|
11
|
+
weight = 1;
|
|
12
|
+
parent;
|
|
13
|
+
left;
|
|
14
|
+
right;
|
|
8
15
|
constructor(key, value) {
|
|
9
16
|
this.key = key;
|
|
10
17
|
this.value = value;
|
|
11
|
-
this.weight = 1;
|
|
12
18
|
}
|
|
13
19
|
weigh() {
|
|
14
|
-
|
|
15
|
-
this.weight = 1 + ((_b = (_a = this.left) === null || _a === void 0 ? void 0 : _a.weight) !== null && _b !== void 0 ? _b : 0) + ((_d = (_c = this.right) === null || _c === void 0 ? void 0 : _c.weight) !== null && _d !== void 0 ? _d : 0);
|
|
20
|
+
this.weight = 1 + (this.left?.weight ?? 0) + (this.right?.weight ?? 0);
|
|
16
21
|
}
|
|
17
22
|
index() {
|
|
18
23
|
let i = -1;
|
|
@@ -60,7 +65,7 @@ class Node {
|
|
|
60
65
|
rotateLeft() {
|
|
61
66
|
let a = this;
|
|
62
67
|
let b = a.right;
|
|
63
|
-
let r = b
|
|
68
|
+
let r = b?.left;
|
|
64
69
|
b.parent = a.parent;
|
|
65
70
|
b.left = a;
|
|
66
71
|
a.parent = b;
|
|
@@ -68,13 +73,13 @@ class Node {
|
|
|
68
73
|
if (r)
|
|
69
74
|
r.parent = a;
|
|
70
75
|
a.weigh();
|
|
71
|
-
b
|
|
76
|
+
b?.weigh();
|
|
72
77
|
return b;
|
|
73
78
|
}
|
|
74
79
|
rotateRight() {
|
|
75
80
|
let a = this;
|
|
76
81
|
let b = a.left;
|
|
77
|
-
let l = b
|
|
82
|
+
let l = b?.right;
|
|
78
83
|
b.parent = a.parent;
|
|
79
84
|
b.right = a;
|
|
80
85
|
a.parent = b;
|
|
@@ -82,7 +87,7 @@ class Node {
|
|
|
82
87
|
if (l)
|
|
83
88
|
l.parent = a;
|
|
84
89
|
a.weigh();
|
|
85
|
-
b
|
|
90
|
+
b?.weigh();
|
|
86
91
|
return b;
|
|
87
92
|
}
|
|
88
93
|
}
|
|
@@ -93,6 +98,9 @@ const LE = { lset: true, rset: false, eset: true, eright: true };
|
|
|
93
98
|
const GT = { lset: false, rset: true, eset: false, eright: true };
|
|
94
99
|
const GE = { lset: false, rset: true, eset: true, eright: false };
|
|
95
100
|
export class TMap extends Base {
|
|
101
|
+
root;
|
|
102
|
+
_compare;
|
|
103
|
+
conf;
|
|
96
104
|
constructor(input, c) {
|
|
97
105
|
super();
|
|
98
106
|
this._compare = c.compare;
|
|
@@ -106,7 +114,7 @@ export class TMap extends Base {
|
|
|
106
114
|
toEmpty() {
|
|
107
115
|
return new TMap([], this.conf);
|
|
108
116
|
}
|
|
109
|
-
get size() {
|
|
117
|
+
get size() { return this.root?.weight ?? 0; }
|
|
110
118
|
clear() {
|
|
111
119
|
const sz = this.size;
|
|
112
120
|
this.root = undefined;
|
|
@@ -122,9 +130,15 @@ export class TMap extends Base {
|
|
|
122
130
|
this.fire({ cleared: sz });
|
|
123
131
|
else
|
|
124
132
|
this.fire({ cleared: sz, added: { items: this, at: 0 } });
|
|
133
|
+
return true;
|
|
125
134
|
}
|
|
126
|
-
else if (this.root !== undefined)
|
|
135
|
+
else if (this.root !== undefined) {
|
|
127
136
|
this.fire({ added: { items: this, at: 0 } });
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
128
142
|
}
|
|
129
143
|
drop(f) {
|
|
130
144
|
let n = this.first;
|
|
@@ -157,7 +171,6 @@ export class TMap extends Base {
|
|
|
157
171
|
this.fire({ cleared: this.size, added: { items: this, at: 0 } });
|
|
158
172
|
}
|
|
159
173
|
at(i) {
|
|
160
|
-
var _a;
|
|
161
174
|
let node = this.root;
|
|
162
175
|
let weight = this.size;
|
|
163
176
|
if (!Number.isSafeInteger(i))
|
|
@@ -165,11 +178,11 @@ export class TMap extends Base {
|
|
|
165
178
|
if (i < 0 || i >= weight)
|
|
166
179
|
throw new TypeError("bounds");
|
|
167
180
|
while (true) {
|
|
168
|
-
const left = node
|
|
169
|
-
const lw =
|
|
181
|
+
const left = node?.left;
|
|
182
|
+
const lw = left?.weight ?? 0;
|
|
170
183
|
if (i > lw) {
|
|
171
184
|
i -= lw + 1;
|
|
172
|
-
node = node
|
|
185
|
+
node = node?.right;
|
|
173
186
|
}
|
|
174
187
|
else if (i < lw) {
|
|
175
188
|
node = left;
|
|
@@ -209,22 +222,31 @@ export class TMap extends Base {
|
|
|
209
222
|
n = n.next();
|
|
210
223
|
}
|
|
211
224
|
}
|
|
212
|
-
|
|
225
|
+
*#keys() {
|
|
213
226
|
for (const x of this)
|
|
214
227
|
yield x.key;
|
|
215
228
|
}
|
|
216
|
-
|
|
229
|
+
keys() {
|
|
230
|
+
return iterable(() => this.#keys());
|
|
231
|
+
}
|
|
232
|
+
*#values() {
|
|
217
233
|
for (const x of this)
|
|
218
234
|
yield x.value;
|
|
219
235
|
}
|
|
220
|
-
|
|
236
|
+
values() {
|
|
237
|
+
return iterable(() => this.#values());
|
|
238
|
+
}
|
|
239
|
+
*#reversed() {
|
|
221
240
|
let n = this.last;
|
|
222
241
|
while (n) {
|
|
223
242
|
yield n;
|
|
224
243
|
n = n.prev();
|
|
225
244
|
}
|
|
226
245
|
}
|
|
227
|
-
|
|
246
|
+
reversed() {
|
|
247
|
+
return iterable(() => this.#reversed());
|
|
248
|
+
}
|
|
249
|
+
*#range(startKey, endKey, inc) {
|
|
228
250
|
const start = this.find(startKey, inc.start ? GE : GT);
|
|
229
251
|
const cmp = this.compare;
|
|
230
252
|
if (inc.end)
|
|
@@ -236,6 +258,21 @@ export class TMap extends Base {
|
|
|
236
258
|
yield n;
|
|
237
259
|
}
|
|
238
260
|
}
|
|
261
|
+
range(startKey, endKey, inc = IN_EX) {
|
|
262
|
+
return iterable(() => this.#range(startKey, endKey, inc));
|
|
263
|
+
}
|
|
264
|
+
slice(start, end) {
|
|
265
|
+
if (end <= start)
|
|
266
|
+
throw new TypeError("end <= start");
|
|
267
|
+
const s = this.at(start);
|
|
268
|
+
if (end === this.size) {
|
|
269
|
+
return this.range(s.key, this.last.key, IN_IN);
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
const e = this.at(end);
|
|
273
|
+
return this.range(s.key, e.key, IN_EX);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
239
276
|
find(key, op = EQ) {
|
|
240
277
|
let node = this.root;
|
|
241
278
|
let ret;
|
|
@@ -265,7 +302,7 @@ export class TMap extends Base {
|
|
|
265
302
|
}
|
|
266
303
|
return ret;
|
|
267
304
|
}
|
|
268
|
-
get(key) {
|
|
305
|
+
get(key) { return this.find(key, EQ)?.value; }
|
|
269
306
|
has(key) { return this.find(key, EQ) !== undefined; }
|
|
270
307
|
from(key) { return this.find(key, GE); }
|
|
271
308
|
to(key) { return this.find(key, LE); }
|
|
@@ -278,8 +315,7 @@ export class TMap extends Base {
|
|
|
278
315
|
return true;
|
|
279
316
|
}
|
|
280
317
|
rank(key) {
|
|
281
|
-
|
|
282
|
-
return (_a = this.find(key, EQ)) === null || _a === void 0 ? void 0 : _a.index();
|
|
318
|
+
return this.find(key, EQ)?.index();
|
|
283
319
|
}
|
|
284
320
|
rawPut(key, value) {
|
|
285
321
|
let previous = undefined, node = this.root;
|
|
@@ -414,13 +450,13 @@ export class TMap extends Base {
|
|
|
414
450
|
let lw = weight(left);
|
|
415
451
|
let rw = weight(right);
|
|
416
452
|
if (rw * 5 + 2 < lw * 2) {
|
|
417
|
-
if (weight(left
|
|
418
|
-
node.left = left
|
|
453
|
+
if (weight(left?.left) * 5 < lw * 2)
|
|
454
|
+
node.left = left?.rotateLeft();
|
|
419
455
|
node = node.rotateRight();
|
|
420
456
|
}
|
|
421
457
|
else if (lw * 5 + 2 < rw * 2) {
|
|
422
|
-
if (weight(right
|
|
423
|
-
node.right = right
|
|
458
|
+
if (weight(right?.right) * 5 < rw * 2)
|
|
459
|
+
node.right = right?.rotateRight();
|
|
424
460
|
node = node.rotateLeft();
|
|
425
461
|
}
|
|
426
462
|
else {
|
|
@@ -437,7 +473,6 @@ export class TMap extends Base {
|
|
|
437
473
|
}
|
|
438
474
|
}
|
|
439
475
|
function weight(n) {
|
|
440
|
-
|
|
441
|
-
return (_a = n === null || n === void 0 ? void 0 : n.weight) !== null && _a !== void 0 ? _a : 0;
|
|
476
|
+
return n?.weight ?? 0;
|
|
442
477
|
}
|
|
443
478
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dubc-ds-tmap",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.2",
|
|
5
5
|
"description": "Observable map based on a weighted binary search tree.",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -26,14 +26,15 @@
|
|
|
26
26
|
},
|
|
27
27
|
"homepage": "https://github.com/p-jack/dubc#readme",
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"
|
|
30
|
-
"dubc-ds-
|
|
29
|
+
"@vitest/coverage-v8": "^4.1.8",
|
|
30
|
+
"dubc-ds-base": "^1.0.3",
|
|
31
|
+
"dubc-ds-iterables": "^1.0.0",
|
|
32
|
+
"dubc-ds-pairs": "^1.0.2",
|
|
33
|
+
"vitest": "^4.1.8"
|
|
31
34
|
},
|
|
32
35
|
"devDependencies": {
|
|
33
|
-
"
|
|
34
|
-
"dubc-ds-test": "^1.0.1",
|
|
36
|
+
"dubc-ds-test": "^1.0.2",
|
|
35
37
|
"jsdom": "^27.0.1",
|
|
36
|
-
"typescript": "^5.9.3"
|
|
37
|
-
"vitest": "^3.2.4"
|
|
38
|
+
"typescript": "^5.9.3"
|
|
38
39
|
}
|
|
39
40
|
}
|