dubc-ds-tmap 1.0.1 → 1.0.5

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 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 iterator over a range of keys in the map. The
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>): void;
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(): Generator<K, void, unknown>;
63
- values(): Generator<V, void, unknown>;
64
- reversed(): Generator<Pair<K, V>, void, unknown>;
65
- range(startKey: K, endKey: K, inc?: Include): Generator<Pair<K, V>, void, unknown>;
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
- var _a, _b, _c, _d;
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 === null || b === void 0 ? void 0 : b.left;
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 === null || b === void 0 ? void 0 : b.weigh();
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 === null || b === void 0 ? void 0 : b.right;
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 === null || b === void 0 ? void 0 : b.weigh();
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() { var _a, _b; return (_b = (_a = this.root) === null || _a === void 0 ? void 0 : _a.weight) !== null && _b !== void 0 ? _b : 0; }
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 === null || node === void 0 ? void 0 : node.left;
169
- const lw = (_a = left === null || left === void 0 ? void 0 : left.weight) !== null && _a !== void 0 ? _a : 0;
181
+ const left = node?.left;
182
+ const lw = left?.weight ?? 0;
170
183
  if (i > lw) {
171
184
  i -= lw + 1;
172
- node = node === null || node === void 0 ? void 0 : node.right;
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
- *keys() {
225
+ *#keys() {
213
226
  for (const x of this)
214
227
  yield x.key;
215
228
  }
216
- *values() {
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
- *reversed() {
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
- *range(startKey, endKey, inc = IN_EX) {
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) { var _a; return (_a = this.find(key, EQ)) === null || _a === void 0 ? void 0 : _a.value; }
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
- var _a;
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 === null || left === void 0 ? void 0 : left.left) * 5 < lw * 2)
418
- node.left = left === null || left === void 0 ? void 0 : left.rotateLeft();
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 === null || right === void 0 ? void 0 : right.right) * 5 < rw * 2)
423
- node.right = right === null || right === void 0 ? void 0 : right.rotateRight();
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
- var _a;
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.1",
4
+ "version": "1.0.5",
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
- "dubc-ds-base": "^1.0.2",
30
- "dubc-ds-pairs": "^1.0.1"
29
+ "dubc-ds-base": "^1.0.5",
30
+ "dubc-ds-iterables": "^1.0.0",
31
+ "dubc-ds-pairs": "^1.0.5"
31
32
  },
32
33
  "devDependencies": {
33
- "@vitest/coverage-v8": "^3.2.4",
34
- "dubc-ds-test": "^1.0.1",
34
+ "@vitest/coverage-v8": "^4.1.8",
35
+ "dubc-ds-test": "^1.0.5",
35
36
  "jsdom": "^27.0.1",
36
37
  "typescript": "^5.9.3",
37
- "vitest": "^3.2.4"
38
+ "vitest": "^4.1.8"
38
39
  }
39
40
  }