data-structure-typed 2.4.4 → 2.5.0
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/CHANGELOG.md +22 -1
- package/README.md +34 -1
- package/dist/cjs/index.cjs +10639 -2151
- package/dist/cjs-legacy/index.cjs +10694 -2195
- package/dist/esm/index.mjs +10639 -2150
- package/dist/esm-legacy/index.mjs +10694 -2194
- package/dist/types/common/error.d.ts +23 -0
- package/dist/types/common/index.d.ts +1 -0
- package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +128 -51
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +210 -164
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +439 -78
- package/dist/types/data-structures/binary-tree/bst.d.ts +311 -28
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +217 -31
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +218 -152
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +1281 -5
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1087 -201
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +858 -65
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +1133 -5
- package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
- package/dist/types/data-structures/graph/directed-graph.d.ts +220 -47
- package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +218 -59
- package/dist/types/data-structures/hash/hash-map.d.ts +230 -77
- package/dist/types/data-structures/heap/heap.d.ts +287 -99
- package/dist/types/data-structures/heap/max-heap.d.ts +46 -0
- package/dist/types/data-structures/heap/min-heap.d.ts +59 -0
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +286 -44
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +278 -65
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +415 -12
- package/dist/types/data-structures/matrix/matrix.d.ts +331 -0
- package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +57 -0
- package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +60 -0
- package/dist/types/data-structures/priority-queue/priority-queue.d.ts +60 -0
- package/dist/types/data-structures/queue/deque.d.ts +313 -66
- package/dist/types/data-structures/queue/queue.d.ts +211 -42
- package/dist/types/data-structures/stack/stack.d.ts +174 -32
- package/dist/types/data-structures/trie/trie.d.ts +213 -43
- package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
- package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
- package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
- package/dist/umd/data-structure-typed.js +10725 -2221
- package/dist/umd/data-structure-typed.min.js +4 -2
- package/package.json +5 -4
- package/src/common/error.ts +60 -0
- package/src/common/index.ts +2 -0
- package/src/data-structures/base/iterable-element-base.ts +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +146 -51
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +317 -247
- package/src/data-structures/binary-tree/binary-tree.ts +567 -121
- package/src/data-structures/binary-tree/bst.ts +370 -37
- package/src/data-structures/binary-tree/red-black-tree.ts +328 -96
- package/src/data-structures/binary-tree/segment-tree.ts +378 -248
- package/src/data-structures/binary-tree/tree-map.ts +1411 -13
- package/src/data-structures/binary-tree/tree-multi-map.ts +1218 -215
- package/src/data-structures/binary-tree/tree-multi-set.ts +959 -69
- package/src/data-structures/binary-tree/tree-set.ts +1257 -15
- package/src/data-structures/graph/abstract-graph.ts +106 -1
- package/src/data-structures/graph/directed-graph.ts +233 -47
- package/src/data-structures/graph/map-graph.ts +59 -1
- package/src/data-structures/graph/undirected-graph.ts +308 -59
- package/src/data-structures/hash/hash-map.ts +254 -79
- package/src/data-structures/heap/heap.ts +305 -102
- package/src/data-structures/heap/max-heap.ts +48 -3
- package/src/data-structures/heap/min-heap.ts +59 -0
- package/src/data-structures/linked-list/doubly-linked-list.ts +303 -44
- package/src/data-structures/linked-list/singly-linked-list.ts +293 -65
- package/src/data-structures/linked-list/skip-linked-list.ts +707 -90
- package/src/data-structures/matrix/matrix.ts +433 -22
- package/src/data-structures/priority-queue/max-priority-queue.ts +59 -3
- package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
- package/src/data-structures/priority-queue/priority-queue.ts +60 -0
- package/src/data-structures/queue/deque.ts +358 -68
- package/src/data-structures/queue/queue.ts +223 -42
- package/src/data-structures/stack/stack.ts +184 -32
- package/src/data-structures/trie/trie.ts +227 -44
- package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
- package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
- package/src/types/data-structures/queue/deque.ts +7 -0
- package/src/utils/utils.ts +4 -2
|
@@ -7,21 +7,10 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { Comparator, TreeMultiMapOptions } from '../../types';
|
|
10
|
-
import { Range } from '../../common';
|
|
10
|
+
import { ERR, Range } from '../../common';
|
|
11
11
|
import { RedBlackTree, RedBlackTreeNode } from './red-black-tree';
|
|
12
12
|
import { TreeSet } from './tree-set';
|
|
13
13
|
|
|
14
|
-
/**
|
|
15
|
-
* Node type used by TreeMultiMap (alias to RedBlackTreeNode for backward compatibility).
|
|
16
|
-
*
|
|
17
|
-
* @deprecated Direct node manipulation is discouraged. Use TreeMultiMap methods instead.
|
|
18
|
-
*/
|
|
19
|
-
export class TreeMultiMapNode<K = any, V = any> extends RedBlackTreeNode<K, V[]> {
|
|
20
|
-
constructor(key: K, value: V[] = []) {
|
|
21
|
-
super(key, value);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
14
|
/**
|
|
26
15
|
* TreeMultiMap (ordered MultiMap) — key → bucket (Array of values).
|
|
27
16
|
*
|
|
@@ -31,169 +20,10 @@ export class TreeMultiMapNode<K = any, V = any> extends RedBlackTreeNode<K, V[]>
|
|
|
31
20
|
* - Default iteration yields bucket entries: `[K, V[]]`.
|
|
32
21
|
* - Navigable operations (`first/last/ceiling/...`) return entry tuples like TreeMap.
|
|
33
22
|
* @example
|
|
34
|
-
* //
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* level: number;
|
|
39
|
-
* };
|
|
40
|
-
*
|
|
41
|
-
* type Player = {
|
|
42
|
-
* name: string;
|
|
43
|
-
* score: number;
|
|
44
|
-
* equipments: Equipment[];
|
|
45
|
-
* };
|
|
46
|
-
*
|
|
47
|
-
* // Mock player data with their scores and equipment
|
|
48
|
-
* const players: Player[] = [
|
|
49
|
-
* {
|
|
50
|
-
* name: 'DragonSlayer',
|
|
51
|
-
* score: 8750,
|
|
52
|
-
* equipments: [
|
|
53
|
-
* { name: 'AWM', quality: 'legendary', level: 85 },
|
|
54
|
-
* { name: 'Level 3 Helmet', quality: 'epic', level: 80 },
|
|
55
|
-
* { name: 'Extended Quickdraw Mag', quality: 'rare', level: 75 },
|
|
56
|
-
* { name: 'Compensator', quality: 'epic', level: 78 },
|
|
57
|
-
* { name: 'Vertical Grip', quality: 'rare', level: 72 }
|
|
58
|
-
* ]
|
|
59
|
-
* },
|
|
60
|
-
* {
|
|
61
|
-
* name: 'ShadowNinja',
|
|
62
|
-
* score: 7200,
|
|
63
|
-
* equipments: [
|
|
64
|
-
* { name: 'M416', quality: 'epic', level: 75 },
|
|
65
|
-
* { name: 'Ghillie Suit', quality: 'rare', level: 70 },
|
|
66
|
-
* { name: 'Red Dot Sight', quality: 'common', level: 65 },
|
|
67
|
-
* { name: 'Extended QuickDraw Mag', quality: 'rare', level: 68 }
|
|
68
|
-
* ]
|
|
69
|
-
* },
|
|
70
|
-
* {
|
|
71
|
-
* name: 'RuneMaster',
|
|
72
|
-
* score: 9100,
|
|
73
|
-
* equipments: [
|
|
74
|
-
* { name: 'KAR98K', quality: 'legendary', level: 90 },
|
|
75
|
-
* { name: 'Level 3 Vest', quality: 'legendary', level: 85 },
|
|
76
|
-
* { name: 'Holographic Sight', quality: 'epic', level: 82 },
|
|
77
|
-
* { name: 'Suppressor', quality: 'legendary', level: 88 },
|
|
78
|
-
* { name: 'Level 3 Backpack', quality: 'epic', level: 80 }
|
|
79
|
-
* ]
|
|
80
|
-
* },
|
|
81
|
-
* {
|
|
82
|
-
* name: 'BattleKing',
|
|
83
|
-
* score: 8500,
|
|
84
|
-
* equipments: [
|
|
85
|
-
* { name: 'AUG', quality: 'epic', level: 82 },
|
|
86
|
-
* { name: 'Red Dot Sight', quality: 'rare', level: 75 },
|
|
87
|
-
* { name: 'Extended Mag', quality: 'common', level: 70 },
|
|
88
|
-
* { name: 'Tactical Stock', quality: 'rare', level: 76 }
|
|
89
|
-
* ]
|
|
90
|
-
* },
|
|
91
|
-
* {
|
|
92
|
-
* name: 'SniperElite',
|
|
93
|
-
* score: 7800,
|
|
94
|
-
* equipments: [
|
|
95
|
-
* { name: 'M24', quality: 'legendary', level: 88 },
|
|
96
|
-
* { name: 'Compensator', quality: 'epic', level: 80 },
|
|
97
|
-
* { name: 'Scope 8x', quality: 'legendary', level: 85 },
|
|
98
|
-
* { name: 'Level 2 Helmet', quality: 'rare', level: 75 }
|
|
99
|
-
* ]
|
|
100
|
-
* },
|
|
101
|
-
* {
|
|
102
|
-
* name: 'RushMaster',
|
|
103
|
-
* score: 7500,
|
|
104
|
-
* equipments: [
|
|
105
|
-
* { name: 'Vector', quality: 'rare', level: 72 },
|
|
106
|
-
* { name: 'Level 2 Helmet', quality: 'common', level: 65 },
|
|
107
|
-
* { name: 'Quickdraw Mag', quality: 'common', level: 60 },
|
|
108
|
-
* { name: 'Laser Sight', quality: 'rare', level: 68 }
|
|
109
|
-
* ]
|
|
110
|
-
* },
|
|
111
|
-
* {
|
|
112
|
-
* name: 'GhostWarrior',
|
|
113
|
-
* score: 8200,
|
|
114
|
-
* equipments: [
|
|
115
|
-
* { name: 'SCAR-L', quality: 'epic', level: 78 },
|
|
116
|
-
* { name: 'Extended Quickdraw Mag', quality: 'rare', level: 70 },
|
|
117
|
-
* { name: 'Holographic Sight', quality: 'epic', level: 75 },
|
|
118
|
-
* { name: 'Suppressor', quality: 'rare', level: 72 },
|
|
119
|
-
* { name: 'Vertical Grip', quality: 'common', level: 65 }
|
|
120
|
-
* ]
|
|
121
|
-
* },
|
|
122
|
-
* {
|
|
123
|
-
* name: 'DeathDealer',
|
|
124
|
-
* score: 7300,
|
|
125
|
-
* equipments: [
|
|
126
|
-
* { name: 'SKS', quality: 'epic', level: 76 },
|
|
127
|
-
* { name: 'Holographic Sight', quality: 'rare', level: 68 },
|
|
128
|
-
* { name: 'Extended Mag', quality: 'common', level: 65 }
|
|
129
|
-
* ]
|
|
130
|
-
* },
|
|
131
|
-
* {
|
|
132
|
-
* name: 'StormRider',
|
|
133
|
-
* score: 8900,
|
|
134
|
-
* equipments: [
|
|
135
|
-
* { name: 'MK14', quality: 'legendary', level: 92 },
|
|
136
|
-
* { name: 'Level 3 Backpack', quality: 'legendary', level: 85 },
|
|
137
|
-
* { name: 'Scope 8x', quality: 'epic', level: 80 },
|
|
138
|
-
* { name: 'Suppressor', quality: 'legendary', level: 88 },
|
|
139
|
-
* { name: 'Tactical Stock', quality: 'rare', level: 75 }
|
|
140
|
-
* ]
|
|
141
|
-
* },
|
|
142
|
-
* {
|
|
143
|
-
* name: 'CombatLegend',
|
|
144
|
-
* score: 7600,
|
|
145
|
-
* equipments: [
|
|
146
|
-
* { name: 'UMP45', quality: 'rare', level: 74 },
|
|
147
|
-
* { name: 'Level 2 Vest', quality: 'common', level: 67 },
|
|
148
|
-
* { name: 'Red Dot Sight', quality: 'common', level: 62 },
|
|
149
|
-
* { name: 'Extended Mag', quality: 'rare', level: 70 }
|
|
150
|
-
* ]
|
|
151
|
-
* }
|
|
152
|
-
* ];
|
|
153
|
-
*
|
|
154
|
-
* // Create a TreeMultiMap for player rankings
|
|
155
|
-
* const playerRankings = new TreeMultiMap<number, Equipment, Player>(players, {
|
|
156
|
-
* toEntryFn: ({ score, equipments }) => [score, equipments],
|
|
157
|
-
* isMapMode: false
|
|
158
|
-
* });
|
|
159
|
-
*
|
|
160
|
-
* const topPlayersEquipments = playerRankings.rangeSearch([8900, 10000], node => playerRankings.get(node.key));
|
|
161
|
-
* console.log(topPlayersEquipments); // [
|
|
162
|
-
* // [
|
|
163
|
-
* // {
|
|
164
|
-
* // name: 'MK14',
|
|
165
|
-
* // quality: 'legendary',
|
|
166
|
-
* // level: 92
|
|
167
|
-
* // },
|
|
168
|
-
* // { name: 'Level 3 Backpack', quality: 'legendary', level: 85 },
|
|
169
|
-
* // {
|
|
170
|
-
* // name: 'Scope 8x',
|
|
171
|
-
* // quality: 'epic',
|
|
172
|
-
* // level: 80
|
|
173
|
-
* // },
|
|
174
|
-
* // { name: 'Suppressor', quality: 'legendary', level: 88 },
|
|
175
|
-
* // {
|
|
176
|
-
* // name: 'Tactical Stock',
|
|
177
|
-
* // quality: 'rare',
|
|
178
|
-
* // level: 75
|
|
179
|
-
* // }
|
|
180
|
-
* // ],
|
|
181
|
-
* // [
|
|
182
|
-
* // { name: 'KAR98K', quality: 'legendary', level: 90 },
|
|
183
|
-
* // {
|
|
184
|
-
* // name: 'Level 3 Vest',
|
|
185
|
-
* // quality: 'legendary',
|
|
186
|
-
* // level: 85
|
|
187
|
-
* // },
|
|
188
|
-
* // { name: 'Holographic Sight', quality: 'epic', level: 82 },
|
|
189
|
-
* // {
|
|
190
|
-
* // name: 'Suppressor',
|
|
191
|
-
* // quality: 'legendary',
|
|
192
|
-
* // level: 88
|
|
193
|
-
* // },
|
|
194
|
-
* // { name: 'Level 3 Backpack', quality: 'epic', level: 80 }
|
|
195
|
-
* // ]
|
|
196
|
-
* // ];
|
|
23
|
+
* // Morris traversal (O(1) space)
|
|
24
|
+
* const tmm = new TreeMultiMap<number>([5, 3, 7]);
|
|
25
|
+
* const result = tmm.morris(n => n.key, 'IN');
|
|
26
|
+
* console.log(result.length); // > 0;
|
|
197
27
|
*/
|
|
198
28
|
export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]]> {
|
|
199
29
|
readonly #core: RedBlackTree<K, V[], R>;
|
|
@@ -261,15 +91,15 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
261
91
|
// reuse TreeSet strict validation (same policy)
|
|
262
92
|
// NOTE: TreeSet._validateKey is private, so we replicate the checks.
|
|
263
93
|
if (typeof key === 'number') {
|
|
264
|
-
if (Number.isNaN(key)) throw new TypeError('TreeMultiMap
|
|
94
|
+
if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN('TreeMultiMap'));
|
|
265
95
|
return;
|
|
266
96
|
}
|
|
267
97
|
if (typeof key === 'string') return;
|
|
268
98
|
if (key instanceof Date) {
|
|
269
|
-
if (Number.isNaN(key.getTime())) throw new TypeError('TreeMultiMap
|
|
99
|
+
if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate('TreeMultiMap'));
|
|
270
100
|
return;
|
|
271
101
|
}
|
|
272
|
-
throw new TypeError('TreeMultiMap
|
|
102
|
+
throw new TypeError(ERR.comparatorRequired('TreeMultiMap'));
|
|
273
103
|
}
|
|
274
104
|
|
|
275
105
|
/**
|
|
@@ -283,6 +113,52 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
283
113
|
/**
|
|
284
114
|
* Whether the map is empty.
|
|
285
115
|
* @remarks Time O(1), Space O(1)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
* @example
|
|
160
|
+
* // Check if empty
|
|
161
|
+
* console.log(new TreeMultiMap().isEmpty()); // true;
|
|
286
162
|
*/
|
|
287
163
|
isEmpty(): boolean {
|
|
288
164
|
return this.size === 0;
|
|
@@ -291,6 +167,55 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
291
167
|
/**
|
|
292
168
|
* Removes all entries from the map.
|
|
293
169
|
* @remarks Time O(1), Space O(1)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
* @example
|
|
214
|
+
* // Remove all entries
|
|
215
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
216
|
+
* mm.add(1, 'a');
|
|
217
|
+
* mm.clear();
|
|
218
|
+
* console.log(mm.isEmpty()); // true;
|
|
294
219
|
*/
|
|
295
220
|
clear(): void {
|
|
296
221
|
this.#core.clear();
|
|
@@ -299,6 +224,15 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
299
224
|
/**
|
|
300
225
|
* Bucket length for a key (missing => 0).
|
|
301
226
|
* @remarks Time O(log n), Space O(1)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
* @example
|
|
231
|
+
* // Count values for key
|
|
232
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
233
|
+
* mm.add(1, 'a');
|
|
234
|
+
* mm.add(1, 'b');
|
|
235
|
+
* console.log(mm.count(1)); // 2;
|
|
302
236
|
*/
|
|
303
237
|
count(key: K): number {
|
|
304
238
|
const b = this.get(key);
|
|
@@ -308,6 +242,16 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
308
242
|
/**
|
|
309
243
|
* Total number of values across all buckets (Σ bucket.length).
|
|
310
244
|
* @remarks Time O(n), Space O(1)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
* @example
|
|
249
|
+
* // Total number of values
|
|
250
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
251
|
+
* mm.add(1, 'a');
|
|
252
|
+
* mm.add(1, 'b');
|
|
253
|
+
* mm.add(2, 'c');
|
|
254
|
+
* console.log(mm.totalSize); // 3;
|
|
311
255
|
*/
|
|
312
256
|
get totalSize(): number {
|
|
313
257
|
let sum = 0;
|
|
@@ -318,6 +262,70 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
318
262
|
/**
|
|
319
263
|
* Whether the map contains the given key.
|
|
320
264
|
* @remarks Time O(log n), Space O(1)
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
* @example
|
|
324
|
+
* // Check key existence
|
|
325
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
326
|
+
* mm.add(1, 'a');
|
|
327
|
+
* console.log(mm.has(1)); // true;
|
|
328
|
+
* console.log(mm.has(2)); // false;
|
|
321
329
|
*/
|
|
322
330
|
has(key: K): boolean {
|
|
323
331
|
this._validateKey(key);
|
|
@@ -327,6 +335,70 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
327
335
|
/**
|
|
328
336
|
* Live bucket reference (do not auto-delete key if bucket becomes empty via mutation).
|
|
329
337
|
* @remarks Time O(log n), Space O(1)
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
* @example
|
|
397
|
+
* // Get values for key
|
|
398
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
399
|
+
* mm.add(1, 'a');
|
|
400
|
+
* mm.add(1, 'b');
|
|
401
|
+
* console.log(mm.get(1)); // ['a', 'b'];
|
|
330
402
|
*/
|
|
331
403
|
get(key: K): V[] | undefined {
|
|
332
404
|
this._validateKey(key);
|
|
@@ -336,6 +408,50 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
336
408
|
/**
|
|
337
409
|
* Append a single value.
|
|
338
410
|
* @remarks Time O(log n), Space O(1)
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
* @example
|
|
449
|
+
* // Add key-value pair
|
|
450
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
451
|
+
* mm.add(1, 'a');
|
|
452
|
+
* mm.add(1, 'b');
|
|
453
|
+
* mm.add(2, 'c');
|
|
454
|
+
* console.log(mm.get(1)); // ['a', 'b'];
|
|
339
455
|
*/
|
|
340
456
|
add(key: K, value: V): boolean {
|
|
341
457
|
this._validateKey(key);
|
|
@@ -350,6 +466,68 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
350
466
|
/**
|
|
351
467
|
* Alias for compatibility with existing TreeMultiMap semantics.
|
|
352
468
|
* @remarks Time O(log n), Space O(1) for single value; O(log n + m) for bucket append
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
* @example
|
|
526
|
+
* // Set values for key
|
|
527
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
528
|
+
* mm.set(1, 'a');
|
|
529
|
+
* mm.set(1, 'b');
|
|
530
|
+
* console.log(mm.get(1)); // ['a', 'b'];
|
|
353
531
|
*/
|
|
354
532
|
set(entry: [K | null | undefined, V[] | undefined] | K | null | undefined, value?: V): boolean;
|
|
355
533
|
set(key: K, value: V): boolean;
|
|
@@ -379,6 +557,71 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
379
557
|
/**
|
|
380
558
|
* Deletes a key and its entire bucket.
|
|
381
559
|
* @remarks Time O(log n), Space O(1)
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
* @example
|
|
619
|
+
* // Remove key
|
|
620
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
621
|
+
* mm.add(1, 'a');
|
|
622
|
+
* mm.add(2, 'b');
|
|
623
|
+
* mm.delete(1);
|
|
624
|
+
* console.log(mm.has(1)); // false;
|
|
382
625
|
*/
|
|
383
626
|
delete(key: K): boolean {
|
|
384
627
|
this._validateKey(key);
|
|
@@ -388,6 +631,15 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
388
631
|
/**
|
|
389
632
|
* Check if a specific value exists in a key's bucket.
|
|
390
633
|
* @remarks Time O(log n + m), Space O(1) where m is bucket size
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
* @example
|
|
638
|
+
* // Check specific key-value
|
|
639
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
640
|
+
* mm.add(1, 'a');
|
|
641
|
+
* console.log(mm.hasEntry(1, 'a')); // true;
|
|
642
|
+
* console.log(mm.hasEntry(1, 'z')); // false;
|
|
391
643
|
*/
|
|
392
644
|
hasEntry(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): boolean {
|
|
393
645
|
const bucket = this.get(key);
|
|
@@ -398,6 +650,16 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
398
650
|
/**
|
|
399
651
|
* Delete a single occurrence of a value from a key's bucket.
|
|
400
652
|
* @remarks Time O(log n + m), Space O(1) where m is bucket size
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
* @example
|
|
657
|
+
* // Delete specific value
|
|
658
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
659
|
+
* mm.add(1, 'a');
|
|
660
|
+
* mm.add(1, 'b');
|
|
661
|
+
* mm.deleteValue(1, 'a');
|
|
662
|
+
* console.log(mm.get(1)); // ['b'];
|
|
401
663
|
*/
|
|
402
664
|
deleteValue(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): boolean {
|
|
403
665
|
const bucket = this.get(key);
|
|
@@ -412,6 +674,17 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
412
674
|
/**
|
|
413
675
|
* Delete all occurrences of a value from a key's bucket.
|
|
414
676
|
* @remarks Time O(log n + m), Space O(1) where m is bucket size
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
* @example
|
|
681
|
+
* // Delete all matching values
|
|
682
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
683
|
+
* mm.add(1, 'a');
|
|
684
|
+
* mm.add(1, 'a');
|
|
685
|
+
* mm.add(1, 'b');
|
|
686
|
+
* const count = mm.deleteValues(1, 'a');
|
|
687
|
+
* console.log(count); // 2;
|
|
415
688
|
*/
|
|
416
689
|
deleteValues(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): number {
|
|
417
690
|
const bucket = this.get(key);
|
|
@@ -436,13 +709,62 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
436
709
|
*[Symbol.iterator](): Iterator<[K, V[]]> {
|
|
437
710
|
for (const [k, v] of this.#core) {
|
|
438
711
|
// core always stores buckets, but guard anyway
|
|
439
|
-
yield [k, v ?? ([] as V[])];
|
|
712
|
+
yield [k, v ?? /* istanbul ignore next */ ([] as V[])];
|
|
440
713
|
}
|
|
441
714
|
}
|
|
442
715
|
|
|
443
716
|
/**
|
|
444
717
|
* Iterates over all keys.
|
|
445
718
|
* @remarks Time O(n), Space O(1)
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
|
|
724
|
+
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
|
|
730
|
+
|
|
731
|
+
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
|
|
745
|
+
|
|
746
|
+
|
|
747
|
+
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
|
|
758
|
+
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
* @example
|
|
763
|
+
* // Iterate keys
|
|
764
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
765
|
+
* mm.add(3, 'c');
|
|
766
|
+
* mm.add(1, 'a');
|
|
767
|
+
* console.log([...mm.keys()]); // [1, 3];
|
|
446
768
|
*/
|
|
447
769
|
*keys(): IterableIterator<K> {
|
|
448
770
|
yield* this.#core.keys();
|
|
@@ -451,6 +773,55 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
451
773
|
/**
|
|
452
774
|
* Iterates over all buckets.
|
|
453
775
|
* @remarks Time O(n), Space O(1)
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
|
|
789
|
+
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
|
|
802
|
+
|
|
803
|
+
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
|
|
809
|
+
|
|
810
|
+
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
|
|
814
|
+
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
|
|
818
|
+
|
|
819
|
+
* @example
|
|
820
|
+
* // Iterate value arrays
|
|
821
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
822
|
+
* mm.add(1, 'a');
|
|
823
|
+
* mm.add(1, 'b');
|
|
824
|
+
* console.log([...mm.values()]); // [['a', 'b']];
|
|
454
825
|
*/
|
|
455
826
|
*values(): IterableIterator<V[]> {
|
|
456
827
|
for (const [, bucket] of this) yield bucket;
|
|
@@ -461,6 +832,15 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
461
832
|
/**
|
|
462
833
|
* Iterates over all entries for a specific key.
|
|
463
834
|
* @remarks Time O(log n + m), Space O(1) where m is bucket size
|
|
835
|
+
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
* @example
|
|
839
|
+
* // Get entries for key
|
|
840
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
841
|
+
* mm.add(1, 'a');
|
|
842
|
+
* mm.add(1, 'b');
|
|
843
|
+
* console.log([...mm.entriesOf(1)]); // [[1, 'a'], [1, 'b']];
|
|
464
844
|
*/
|
|
465
845
|
*entriesOf(key: K): IterableIterator<[K, V]> {
|
|
466
846
|
const bucket = this.get(key);
|
|
@@ -471,6 +851,15 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
471
851
|
/**
|
|
472
852
|
* Iterates over all values for a specific key.
|
|
473
853
|
* @remarks Time O(log n + m), Space O(1) where m is bucket size
|
|
854
|
+
|
|
855
|
+
|
|
856
|
+
|
|
857
|
+
* @example
|
|
858
|
+
* // Get flat values for key
|
|
859
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
860
|
+
* mm.add(1, 'a');
|
|
861
|
+
* mm.add(1, 'b');
|
|
862
|
+
* console.log([...mm.valuesOf(1)]); // ['a', 'b'];
|
|
474
863
|
*/
|
|
475
864
|
*valuesOf(key: K): IterableIterator<V> {
|
|
476
865
|
const bucket = this.get(key);
|
|
@@ -481,6 +870,16 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
481
870
|
/**
|
|
482
871
|
* Iterates over all [key, value] pairs (flattened from buckets).
|
|
483
872
|
* @remarks Time O(T), Space O(1) where T is totalSize
|
|
873
|
+
|
|
874
|
+
|
|
875
|
+
|
|
876
|
+
* @example
|
|
877
|
+
* // All key-value pairs flattened
|
|
878
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
879
|
+
* mm.add(1, 'a');
|
|
880
|
+
* mm.add(1, 'b');
|
|
881
|
+
* mm.add(2, 'c');
|
|
882
|
+
* console.log([...mm.flatEntries()]); // [[1, 'a'], [1, 'b'], [2, 'c']];
|
|
484
883
|
*/
|
|
485
884
|
*flatEntries(): IterableIterator<[K, V]> {
|
|
486
885
|
for (const [k, bucket] of this) {
|
|
@@ -493,38 +892,84 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
493
892
|
/**
|
|
494
893
|
* Returns the entry with the smallest key.
|
|
495
894
|
* @remarks Time O(log n), Space O(1)
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
895
|
+
|
|
896
|
+
|
|
897
|
+
|
|
898
|
+
|
|
899
|
+
|
|
900
|
+
|
|
901
|
+
|
|
902
|
+
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
|
|
907
|
+
|
|
908
|
+
|
|
909
|
+
|
|
910
|
+
|
|
911
|
+
* @example
|
|
912
|
+
* // First entry
|
|
913
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
914
|
+
* mm.add(3, 'c');
|
|
915
|
+
* mm.add(1, 'a');
|
|
916
|
+
* console.log(mm.first()?.[0]); // 1;
|
|
499
917
|
*/
|
|
500
918
|
first(): [K, V[]] | undefined {
|
|
501
919
|
const k = this.#core.getLeftMost();
|
|
502
920
|
if (k === undefined) return undefined;
|
|
503
921
|
const b = this.get(k);
|
|
504
|
-
return b === undefined ? undefined : [k, b];
|
|
922
|
+
return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
|
|
505
923
|
}
|
|
506
924
|
|
|
507
925
|
/**
|
|
508
926
|
* Returns the entry with the largest key.
|
|
509
927
|
* @remarks Time O(log n), Space O(1)
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
|
|
932
|
+
|
|
933
|
+
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
|
|
944
|
+
* @example
|
|
945
|
+
* // Last entry
|
|
946
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
947
|
+
* mm.add(1, 'a');
|
|
948
|
+
* mm.add(3, 'c');
|
|
949
|
+
* console.log(mm.last()?.[0]); // 3;
|
|
513
950
|
*/
|
|
514
951
|
last(): [K, V[]] | undefined {
|
|
515
952
|
const k = this.#core.getRightMost();
|
|
516
953
|
if (k === undefined) return undefined;
|
|
517
954
|
const b = this.get(k);
|
|
518
|
-
return b === undefined ? undefined : [k, b];
|
|
955
|
+
return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
|
|
519
956
|
}
|
|
520
957
|
|
|
521
958
|
/**
|
|
522
959
|
* Removes and returns the entry with the smallest key.
|
|
523
960
|
* @remarks Time O(log n), Space O(1)
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
|
|
965
|
+
* @example
|
|
966
|
+
* // Remove and return first
|
|
967
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
968
|
+
* mm.add(2, 'b');
|
|
969
|
+
* mm.add(1, 'a');
|
|
970
|
+
* const first = mm.pollFirst();
|
|
971
|
+
* console.log(first?.[0]); // 1;
|
|
972
|
+
* console.log(mm.has(1)); // false;
|
|
528
973
|
*/
|
|
529
974
|
pollFirst(): [K, V[]] | undefined {
|
|
530
975
|
const e = this.first();
|
|
@@ -536,10 +981,17 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
536
981
|
/**
|
|
537
982
|
* Removes and returns the entry with the largest key.
|
|
538
983
|
* @remarks Time O(log n), Space O(1)
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
* @example
|
|
989
|
+
* // Remove and return last
|
|
990
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
991
|
+
* mm.add(1, 'a');
|
|
992
|
+
* mm.add(3, 'c');
|
|
993
|
+
* const last = mm.pollLast();
|
|
994
|
+
* console.log(last?.[0]); // 3;
|
|
543
995
|
*/
|
|
544
996
|
pollLast(): [K, V[]] | undefined {
|
|
545
997
|
const e = this.last();
|
|
@@ -551,65 +1003,235 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
551
1003
|
/**
|
|
552
1004
|
* Returns the entry with the smallest key >= given key.
|
|
553
1005
|
* @remarks Time O(log n), Space O(1)
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
|
+
|
|
1009
|
+
|
|
1010
|
+
|
|
1011
|
+
|
|
1012
|
+
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
|
|
1016
|
+
|
|
1017
|
+
|
|
1018
|
+
|
|
1019
|
+
|
|
1020
|
+
|
|
1021
|
+
|
|
1022
|
+
|
|
1023
|
+
|
|
1024
|
+
|
|
1025
|
+
|
|
1026
|
+
|
|
1027
|
+
|
|
1028
|
+
|
|
1029
|
+
|
|
1030
|
+
|
|
1031
|
+
|
|
1032
|
+
|
|
1033
|
+
|
|
1034
|
+
|
|
1035
|
+
|
|
1036
|
+
|
|
1037
|
+
|
|
1038
|
+
|
|
1039
|
+
|
|
1040
|
+
|
|
1041
|
+
|
|
1042
|
+
|
|
1043
|
+
|
|
1044
|
+
|
|
1045
|
+
|
|
1046
|
+
|
|
1047
|
+
|
|
1048
|
+
|
|
1049
|
+
|
|
1050
|
+
|
|
1051
|
+
|
|
1052
|
+
* @example
|
|
1053
|
+
* // Least key ≥ target
|
|
1054
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1055
|
+
* mm.add(10, 'a');
|
|
1056
|
+
* mm.add(20, 'b');
|
|
1057
|
+
* mm.add(30, 'c');
|
|
1058
|
+
* console.log(mm.ceiling(15)?.[0]); // 20;
|
|
558
1059
|
*/
|
|
559
1060
|
ceiling(key: K): [K, V[]] | undefined {
|
|
560
1061
|
this._validateKey(key);
|
|
561
1062
|
const k = this.#core.ceiling(key);
|
|
562
1063
|
if (k === undefined) return undefined;
|
|
563
1064
|
const b = this.get(k);
|
|
564
|
-
return b === undefined ? undefined : [k, b];
|
|
1065
|
+
return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
|
|
565
1066
|
}
|
|
566
1067
|
|
|
567
1068
|
/**
|
|
568
1069
|
* Returns the entry with the largest key <= given key.
|
|
569
1070
|
* @remarks Time O(log n), Space O(1)
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
1071
|
+
|
|
1072
|
+
|
|
1073
|
+
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
|
|
1077
|
+
|
|
1078
|
+
|
|
1079
|
+
|
|
1080
|
+
|
|
1081
|
+
|
|
1082
|
+
|
|
1083
|
+
|
|
1084
|
+
|
|
1085
|
+
|
|
1086
|
+
|
|
1087
|
+
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
|
|
1091
|
+
|
|
1092
|
+
|
|
1093
|
+
|
|
1094
|
+
|
|
1095
|
+
|
|
1096
|
+
|
|
1097
|
+
|
|
1098
|
+
|
|
1099
|
+
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
|
|
1103
|
+
|
|
1104
|
+
|
|
1105
|
+
|
|
1106
|
+
|
|
1107
|
+
|
|
1108
|
+
|
|
1109
|
+
|
|
1110
|
+
|
|
1111
|
+
|
|
1112
|
+
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
|
|
1116
|
+
|
|
1117
|
+
* @example
|
|
1118
|
+
* // Greatest key ≤ target
|
|
1119
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1120
|
+
* mm.add(10, 'a');
|
|
1121
|
+
* mm.add(20, 'b');
|
|
1122
|
+
* mm.add(30, 'c');
|
|
1123
|
+
* console.log(mm.floor(25)?.[0]); // 20;
|
|
574
1124
|
*/
|
|
575
1125
|
floor(key: K): [K, V[]] | undefined {
|
|
576
1126
|
this._validateKey(key);
|
|
577
1127
|
const k = this.#core.floor(key);
|
|
578
1128
|
if (k === undefined) return undefined;
|
|
579
1129
|
const b = this.get(k);
|
|
580
|
-
return b === undefined ? undefined : [k, b];
|
|
1130
|
+
return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
|
|
581
1131
|
}
|
|
582
1132
|
|
|
583
1133
|
/**
|
|
584
1134
|
* Returns the entry with the smallest key > given key.
|
|
585
1135
|
* @remarks Time O(log n), Space O(1)
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
|
|
1142
|
+
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
|
|
1146
|
+
|
|
1147
|
+
|
|
1148
|
+
|
|
1149
|
+
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
|
|
1153
|
+
|
|
1154
|
+
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
|
|
1158
|
+
|
|
1159
|
+
|
|
1160
|
+
|
|
1161
|
+
|
|
1162
|
+
|
|
1163
|
+
|
|
1164
|
+
|
|
1165
|
+
|
|
1166
|
+
|
|
1167
|
+
|
|
1168
|
+
|
|
1169
|
+
|
|
1170
|
+
* @example
|
|
1171
|
+
* // Least key > target
|
|
1172
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1173
|
+
* mm.add(10, 'a');
|
|
1174
|
+
* mm.add(20, 'b');
|
|
1175
|
+
* console.log(mm.higher(10)?.[0]); // 20;
|
|
590
1176
|
*/
|
|
591
1177
|
higher(key: K): [K, V[]] | undefined {
|
|
592
1178
|
this._validateKey(key);
|
|
593
1179
|
const k = this.#core.higher(key);
|
|
594
1180
|
if (k === undefined) return undefined;
|
|
595
1181
|
const b = this.get(k);
|
|
596
|
-
return b === undefined ? undefined : [k, b];
|
|
1182
|
+
return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
|
|
597
1183
|
}
|
|
598
1184
|
|
|
599
1185
|
/**
|
|
600
1186
|
* Returns the entry with the largest key < given key.
|
|
601
1187
|
* @remarks Time O(log n), Space O(1)
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
1188
|
+
|
|
1189
|
+
|
|
1190
|
+
|
|
1191
|
+
|
|
1192
|
+
|
|
1193
|
+
|
|
1194
|
+
|
|
1195
|
+
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
|
|
1199
|
+
|
|
1200
|
+
|
|
1201
|
+
|
|
1202
|
+
|
|
1203
|
+
|
|
1204
|
+
|
|
1205
|
+
|
|
1206
|
+
|
|
1207
|
+
|
|
1208
|
+
|
|
1209
|
+
|
|
1210
|
+
|
|
1211
|
+
|
|
1212
|
+
|
|
1213
|
+
|
|
1214
|
+
|
|
1215
|
+
|
|
1216
|
+
|
|
1217
|
+
|
|
1218
|
+
|
|
1219
|
+
|
|
1220
|
+
|
|
1221
|
+
|
|
1222
|
+
* @example
|
|
1223
|
+
* // Greatest key < target
|
|
1224
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1225
|
+
* mm.add(10, 'a');
|
|
1226
|
+
* mm.add(20, 'b');
|
|
1227
|
+
* console.log(mm.lower(20)?.[0]); // 10;
|
|
606
1228
|
*/
|
|
607
1229
|
lower(key: K): [K, V[]] | undefined {
|
|
608
1230
|
this._validateKey(key);
|
|
609
1231
|
const k = this.#core.lower(key);
|
|
610
1232
|
if (k === undefined) return undefined;
|
|
611
1233
|
const b = this.get(k);
|
|
612
|
-
return b === undefined ? undefined : [k, b];
|
|
1234
|
+
return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
|
|
613
1235
|
}
|
|
614
1236
|
|
|
615
1237
|
// ━━━ Tree utilities ━━━
|
|
@@ -617,6 +1239,54 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
617
1239
|
/**
|
|
618
1240
|
* Prints the internal tree structure (for debugging).
|
|
619
1241
|
* @remarks Time O(n), Space O(n)
|
|
1242
|
+
|
|
1243
|
+
|
|
1244
|
+
|
|
1245
|
+
|
|
1246
|
+
|
|
1247
|
+
|
|
1248
|
+
|
|
1249
|
+
|
|
1250
|
+
|
|
1251
|
+
|
|
1252
|
+
|
|
1253
|
+
|
|
1254
|
+
|
|
1255
|
+
|
|
1256
|
+
|
|
1257
|
+
|
|
1258
|
+
|
|
1259
|
+
|
|
1260
|
+
|
|
1261
|
+
|
|
1262
|
+
|
|
1263
|
+
|
|
1264
|
+
|
|
1265
|
+
|
|
1266
|
+
|
|
1267
|
+
|
|
1268
|
+
|
|
1269
|
+
|
|
1270
|
+
|
|
1271
|
+
|
|
1272
|
+
|
|
1273
|
+
|
|
1274
|
+
|
|
1275
|
+
|
|
1276
|
+
|
|
1277
|
+
|
|
1278
|
+
|
|
1279
|
+
|
|
1280
|
+
|
|
1281
|
+
|
|
1282
|
+
|
|
1283
|
+
|
|
1284
|
+
|
|
1285
|
+
* @example
|
|
1286
|
+
* // Display tree
|
|
1287
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1288
|
+
* mm.add(1, 'a');
|
|
1289
|
+
* expect(() => mm.print()).not.toThrow();
|
|
620
1290
|
*/
|
|
621
1291
|
print(): void {
|
|
622
1292
|
this.#core.print();
|
|
@@ -625,6 +1295,57 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
625
1295
|
/**
|
|
626
1296
|
* Executes a callback for each entry.
|
|
627
1297
|
* @remarks Time O(n), Space O(1)
|
|
1298
|
+
|
|
1299
|
+
|
|
1300
|
+
|
|
1301
|
+
|
|
1302
|
+
|
|
1303
|
+
|
|
1304
|
+
|
|
1305
|
+
|
|
1306
|
+
|
|
1307
|
+
|
|
1308
|
+
|
|
1309
|
+
|
|
1310
|
+
|
|
1311
|
+
|
|
1312
|
+
|
|
1313
|
+
|
|
1314
|
+
|
|
1315
|
+
|
|
1316
|
+
|
|
1317
|
+
|
|
1318
|
+
|
|
1319
|
+
|
|
1320
|
+
|
|
1321
|
+
|
|
1322
|
+
|
|
1323
|
+
|
|
1324
|
+
|
|
1325
|
+
|
|
1326
|
+
|
|
1327
|
+
|
|
1328
|
+
|
|
1329
|
+
|
|
1330
|
+
|
|
1331
|
+
|
|
1332
|
+
|
|
1333
|
+
|
|
1334
|
+
|
|
1335
|
+
|
|
1336
|
+
|
|
1337
|
+
|
|
1338
|
+
|
|
1339
|
+
|
|
1340
|
+
|
|
1341
|
+
* @example
|
|
1342
|
+
* // Iterate entries
|
|
1343
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1344
|
+
* mm.add(1, 'a');
|
|
1345
|
+
* mm.add(2, 'b');
|
|
1346
|
+
* const keys: number[] = [];
|
|
1347
|
+
* mm.forEach((v, k) => keys.push(k));
|
|
1348
|
+
* console.log(keys); // [1, 2];
|
|
628
1349
|
*/
|
|
629
1350
|
forEach(callback: (value: V[], key: K, map: this) => void): void {
|
|
630
1351
|
for (const [k, v] of this) {
|
|
@@ -635,6 +1356,57 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
635
1356
|
/**
|
|
636
1357
|
* Creates a new map with entries that pass the predicate.
|
|
637
1358
|
* @remarks Time O(n), Space O(n)
|
|
1359
|
+
|
|
1360
|
+
|
|
1361
|
+
|
|
1362
|
+
|
|
1363
|
+
|
|
1364
|
+
|
|
1365
|
+
|
|
1366
|
+
|
|
1367
|
+
|
|
1368
|
+
|
|
1369
|
+
|
|
1370
|
+
|
|
1371
|
+
|
|
1372
|
+
|
|
1373
|
+
|
|
1374
|
+
|
|
1375
|
+
|
|
1376
|
+
|
|
1377
|
+
|
|
1378
|
+
|
|
1379
|
+
|
|
1380
|
+
|
|
1381
|
+
|
|
1382
|
+
|
|
1383
|
+
|
|
1384
|
+
|
|
1385
|
+
|
|
1386
|
+
|
|
1387
|
+
|
|
1388
|
+
|
|
1389
|
+
|
|
1390
|
+
|
|
1391
|
+
|
|
1392
|
+
|
|
1393
|
+
|
|
1394
|
+
|
|
1395
|
+
|
|
1396
|
+
|
|
1397
|
+
|
|
1398
|
+
|
|
1399
|
+
|
|
1400
|
+
|
|
1401
|
+
|
|
1402
|
+
* @example
|
|
1403
|
+
* // Filter entries
|
|
1404
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1405
|
+
* mm.add(1, 'a');
|
|
1406
|
+
* mm.add(2, 'b');
|
|
1407
|
+
* mm.add(3, 'c');
|
|
1408
|
+
* const filtered = mm.filter((v, k) => k > 1);
|
|
1409
|
+
* console.log([...filtered.keys()]); // [2, 3];
|
|
638
1410
|
*/
|
|
639
1411
|
filter(predicate: (value: V[], key: K, map: this) => boolean): TreeMultiMap<K, V, R> {
|
|
640
1412
|
const filtered: [K, V[]][] = [];
|
|
@@ -647,6 +1419,55 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
647
1419
|
/**
|
|
648
1420
|
* Creates a new map by transforming each entry.
|
|
649
1421
|
* @remarks Time O(n log n), Space O(n)
|
|
1422
|
+
|
|
1423
|
+
|
|
1424
|
+
|
|
1425
|
+
|
|
1426
|
+
|
|
1427
|
+
|
|
1428
|
+
|
|
1429
|
+
|
|
1430
|
+
|
|
1431
|
+
|
|
1432
|
+
|
|
1433
|
+
|
|
1434
|
+
|
|
1435
|
+
|
|
1436
|
+
|
|
1437
|
+
|
|
1438
|
+
|
|
1439
|
+
|
|
1440
|
+
|
|
1441
|
+
|
|
1442
|
+
|
|
1443
|
+
|
|
1444
|
+
|
|
1445
|
+
|
|
1446
|
+
|
|
1447
|
+
|
|
1448
|
+
|
|
1449
|
+
|
|
1450
|
+
|
|
1451
|
+
|
|
1452
|
+
|
|
1453
|
+
|
|
1454
|
+
|
|
1455
|
+
|
|
1456
|
+
|
|
1457
|
+
|
|
1458
|
+
|
|
1459
|
+
|
|
1460
|
+
|
|
1461
|
+
|
|
1462
|
+
|
|
1463
|
+
|
|
1464
|
+
|
|
1465
|
+
* @example
|
|
1466
|
+
* // Transform values
|
|
1467
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1468
|
+
* mm.add(1, 'a');
|
|
1469
|
+
* const mapped = mm.map((v, k) => [k, v.map(s => s.toUpperCase())] as [number, string[]]);
|
|
1470
|
+
* console.log(mapped.get(1)); // ['A'];
|
|
650
1471
|
*/
|
|
651
1472
|
map<V2>(
|
|
652
1473
|
mapper: (value: V[], key: K, map: this) => [K, V2[]]
|
|
@@ -661,6 +1482,56 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
661
1482
|
/**
|
|
662
1483
|
* Reduces all entries to a single value.
|
|
663
1484
|
* @remarks Time O(n), Space O(1)
|
|
1485
|
+
|
|
1486
|
+
|
|
1487
|
+
|
|
1488
|
+
|
|
1489
|
+
|
|
1490
|
+
|
|
1491
|
+
|
|
1492
|
+
|
|
1493
|
+
|
|
1494
|
+
|
|
1495
|
+
|
|
1496
|
+
|
|
1497
|
+
|
|
1498
|
+
|
|
1499
|
+
|
|
1500
|
+
|
|
1501
|
+
|
|
1502
|
+
|
|
1503
|
+
|
|
1504
|
+
|
|
1505
|
+
|
|
1506
|
+
|
|
1507
|
+
|
|
1508
|
+
|
|
1509
|
+
|
|
1510
|
+
|
|
1511
|
+
|
|
1512
|
+
|
|
1513
|
+
|
|
1514
|
+
|
|
1515
|
+
|
|
1516
|
+
|
|
1517
|
+
|
|
1518
|
+
|
|
1519
|
+
|
|
1520
|
+
|
|
1521
|
+
|
|
1522
|
+
|
|
1523
|
+
|
|
1524
|
+
|
|
1525
|
+
|
|
1526
|
+
|
|
1527
|
+
|
|
1528
|
+
* @example
|
|
1529
|
+
* // Aggregate
|
|
1530
|
+
* const mm = new TreeMultiMap<number, number>();
|
|
1531
|
+
* mm.add(1, 10);
|
|
1532
|
+
* mm.add(2, 20);
|
|
1533
|
+
* const sum = mm.reduce((acc, v) => acc + v.reduce((a, b) => a + b, 0), 0);
|
|
1534
|
+
* console.log(sum); // 30;
|
|
664
1535
|
*/
|
|
665
1536
|
reduce<U>(callback: (accumulator: U, value: V[], key: K, map: this) => U, initialValue: U): U {
|
|
666
1537
|
let acc = initialValue;
|
|
@@ -673,6 +1544,46 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
673
1544
|
/**
|
|
674
1545
|
* Sets multiple entries at once.
|
|
675
1546
|
* @remarks Time O(m log n), Space O(m) where m is input size
|
|
1547
|
+
|
|
1548
|
+
|
|
1549
|
+
|
|
1550
|
+
|
|
1551
|
+
|
|
1552
|
+
|
|
1553
|
+
|
|
1554
|
+
|
|
1555
|
+
|
|
1556
|
+
|
|
1557
|
+
|
|
1558
|
+
|
|
1559
|
+
|
|
1560
|
+
|
|
1561
|
+
|
|
1562
|
+
|
|
1563
|
+
|
|
1564
|
+
|
|
1565
|
+
|
|
1566
|
+
|
|
1567
|
+
|
|
1568
|
+
|
|
1569
|
+
|
|
1570
|
+
|
|
1571
|
+
|
|
1572
|
+
|
|
1573
|
+
|
|
1574
|
+
|
|
1575
|
+
|
|
1576
|
+
|
|
1577
|
+
|
|
1578
|
+
|
|
1579
|
+
|
|
1580
|
+
|
|
1581
|
+
|
|
1582
|
+
* @example
|
|
1583
|
+
* // Set multiple entries
|
|
1584
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1585
|
+
* mm.setMany([[1, ['a']], [2, ['b']]]);
|
|
1586
|
+
* console.log(mm.size); // 2;
|
|
676
1587
|
*/
|
|
677
1588
|
setMany(keysNodesEntriesOrRaws: Iterable<K | [K | null | undefined, V[] | undefined]>): boolean[] {
|
|
678
1589
|
const results: boolean[] = [];
|
|
@@ -686,6 +1597,48 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
686
1597
|
/**
|
|
687
1598
|
* Searches for entries within a key range.
|
|
688
1599
|
* @remarks Time O(log n + k), Space O(k) where k is result size
|
|
1600
|
+
|
|
1601
|
+
|
|
1602
|
+
|
|
1603
|
+
|
|
1604
|
+
|
|
1605
|
+
|
|
1606
|
+
|
|
1607
|
+
|
|
1608
|
+
|
|
1609
|
+
|
|
1610
|
+
|
|
1611
|
+
|
|
1612
|
+
|
|
1613
|
+
|
|
1614
|
+
|
|
1615
|
+
|
|
1616
|
+
|
|
1617
|
+
|
|
1618
|
+
|
|
1619
|
+
|
|
1620
|
+
|
|
1621
|
+
|
|
1622
|
+
|
|
1623
|
+
|
|
1624
|
+
|
|
1625
|
+
|
|
1626
|
+
|
|
1627
|
+
|
|
1628
|
+
|
|
1629
|
+
|
|
1630
|
+
|
|
1631
|
+
|
|
1632
|
+
|
|
1633
|
+
|
|
1634
|
+
* @example
|
|
1635
|
+
* // Find keys in range
|
|
1636
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1637
|
+
* mm.add(10, 'a');
|
|
1638
|
+
* mm.add(20, 'b');
|
|
1639
|
+
* mm.add(30, 'c');
|
|
1640
|
+
* const result = mm.rangeSearch([15, 25]);
|
|
1641
|
+
* console.log(result.length); // 1;
|
|
689
1642
|
*/
|
|
690
1643
|
rangeSearch<C extends (node: RedBlackTreeNode<K, V[]>) => unknown>(
|
|
691
1644
|
range: Range<K> | [K, K],
|
|
@@ -697,6 +1650,56 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
697
1650
|
/**
|
|
698
1651
|
* Creates a shallow clone of this map.
|
|
699
1652
|
* @remarks Time O(n log n), Space O(n)
|
|
1653
|
+
|
|
1654
|
+
|
|
1655
|
+
|
|
1656
|
+
|
|
1657
|
+
|
|
1658
|
+
|
|
1659
|
+
|
|
1660
|
+
|
|
1661
|
+
|
|
1662
|
+
|
|
1663
|
+
|
|
1664
|
+
|
|
1665
|
+
|
|
1666
|
+
|
|
1667
|
+
|
|
1668
|
+
|
|
1669
|
+
|
|
1670
|
+
|
|
1671
|
+
|
|
1672
|
+
|
|
1673
|
+
|
|
1674
|
+
|
|
1675
|
+
|
|
1676
|
+
|
|
1677
|
+
|
|
1678
|
+
|
|
1679
|
+
|
|
1680
|
+
|
|
1681
|
+
|
|
1682
|
+
|
|
1683
|
+
|
|
1684
|
+
|
|
1685
|
+
|
|
1686
|
+
|
|
1687
|
+
|
|
1688
|
+
|
|
1689
|
+
|
|
1690
|
+
|
|
1691
|
+
|
|
1692
|
+
|
|
1693
|
+
|
|
1694
|
+
|
|
1695
|
+
|
|
1696
|
+
* @example
|
|
1697
|
+
* // Deep clone
|
|
1698
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1699
|
+
* mm.add(1, 'a');
|
|
1700
|
+
* const copy = mm.clone();
|
|
1701
|
+
* copy.delete(1);
|
|
1702
|
+
* console.log(mm.has(1)); // true;
|
|
700
1703
|
*/
|
|
701
1704
|
clone(): TreeMultiMap<K, V, R> {
|
|
702
1705
|
return new TreeMultiMap<K, V, R>(this, { comparator: this.comparator, isMapMode: this.#core.isMapMode });
|