data-structure-typed 2.5.0 → 2.5.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/.vitepress/cache/deps_temp_51f5f1b0/chunk-7OIKW5WK.js +12984 -0
- package/.vitepress/cache/deps_temp_51f5f1b0/package.json +3 -0
- package/.vitepress/cache/deps_temp_51f5f1b0/vitepress___@vue_devtools-api.js +4505 -0
- package/.vitepress/cache/deps_temp_51f5f1b0/vitepress___@vueuse_core.js +9731 -0
- package/.vitepress/cache/deps_temp_51f5f1b0/vue.js +347 -0
- package/CHANGELOG.md +5 -1
- package/README.md +124 -29
- package/dist/cjs/binary-tree.cjs +26282 -0
- package/dist/cjs/graph.cjs +5422 -0
- package/dist/cjs/hash.cjs +1310 -0
- package/dist/cjs/heap.cjs +1602 -0
- package/dist/cjs/index.cjs +31257 -14673
- package/dist/cjs/linked-list.cjs +4576 -0
- package/dist/cjs/matrix.cjs +1080 -0
- package/dist/cjs/priority-queue.cjs +1376 -0
- package/dist/cjs/queue.cjs +4264 -0
- package/dist/cjs/stack.cjs +907 -0
- package/dist/cjs/trie.cjs +1223 -0
- package/dist/cjs-legacy/binary-tree.cjs +26319 -0
- package/dist/cjs-legacy/graph.cjs +5420 -0
- package/dist/cjs-legacy/hash.cjs +1310 -0
- package/dist/cjs-legacy/heap.cjs +1599 -0
- package/dist/cjs-legacy/index.cjs +31268 -14679
- package/dist/cjs-legacy/linked-list.cjs +4582 -0
- package/dist/cjs-legacy/matrix.cjs +1083 -0
- package/dist/cjs-legacy/priority-queue.cjs +1374 -0
- package/dist/cjs-legacy/queue.cjs +4262 -0
- package/dist/cjs-legacy/stack.cjs +907 -0
- package/dist/cjs-legacy/trie.cjs +1222 -0
- package/dist/esm/binary-tree.mjs +26267 -0
- package/dist/esm/graph.mjs +5409 -0
- package/dist/esm/hash.mjs +1307 -0
- package/dist/esm/heap.mjs +1596 -0
- package/dist/esm/index.mjs +31254 -14674
- package/dist/esm/linked-list.mjs +4569 -0
- package/dist/esm/matrix.mjs +1076 -0
- package/dist/esm/priority-queue.mjs +1372 -0
- package/dist/esm/queue.mjs +4260 -0
- package/dist/esm/stack.mjs +905 -0
- package/dist/esm/trie.mjs +1220 -0
- package/dist/esm-legacy/binary-tree.mjs +26304 -0
- package/dist/esm-legacy/graph.mjs +5407 -0
- package/dist/esm-legacy/hash.mjs +1307 -0
- package/dist/esm-legacy/heap.mjs +1593 -0
- package/dist/esm-legacy/index.mjs +31265 -14680
- package/dist/esm-legacy/linked-list.mjs +4575 -0
- package/dist/esm-legacy/matrix.mjs +1079 -0
- package/dist/esm-legacy/priority-queue.mjs +1370 -0
- package/dist/esm-legacy/queue.mjs +4258 -0
- package/dist/esm-legacy/stack.mjs +905 -0
- package/dist/esm-legacy/trie.mjs +1219 -0
- package/dist/types/common/error.d.ts +9 -0
- package/dist/types/common/index.d.ts +1 -1
- package/dist/types/data-structures/base/index.d.ts +1 -0
- package/dist/types/data-structures/base/iterable-entry-base.d.ts +8 -8
- package/dist/types/data-structures/base/linear-base.d.ts +3 -3
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +288 -0
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +336 -0
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +618 -18
- package/dist/types/data-structures/binary-tree/bst.d.ts +676 -1
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +456 -0
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +144 -1
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +3307 -399
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +3285 -360
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +2674 -325
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +3072 -287
- package/dist/types/data-structures/graph/abstract-graph.d.ts +4 -4
- package/dist/types/data-structures/graph/directed-graph.d.ts +240 -0
- package/dist/types/data-structures/graph/undirected-graph.d.ts +216 -0
- package/dist/types/data-structures/hash/hash-map.d.ts +274 -10
- package/dist/types/data-structures/heap/heap.d.ts +336 -0
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +411 -3
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +363 -3
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +434 -2
- package/dist/types/data-structures/matrix/matrix.d.ts +192 -0
- package/dist/types/data-structures/queue/deque.d.ts +364 -4
- package/dist/types/data-structures/queue/queue.d.ts +288 -0
- package/dist/types/data-structures/stack/stack.d.ts +240 -0
- package/dist/types/data-structures/trie/trie.d.ts +292 -4
- package/dist/types/interfaces/graph.d.ts +1 -1
- package/dist/types/types/common.d.ts +2 -2
- package/dist/types/types/data-structures/binary-tree/bst.d.ts +1 -0
- package/dist/types/types/data-structures/binary-tree/tree-map.d.ts +5 -0
- package/dist/types/types/data-structures/binary-tree/tree-multi-set.d.ts +4 -0
- package/dist/types/types/data-structures/binary-tree/tree-set.d.ts +4 -0
- package/dist/types/types/data-structures/heap/heap.d.ts +1 -0
- package/dist/types/types/data-structures/priority-queue/priority-queue.d.ts +1 -0
- package/dist/types/types/utils/validate-type.d.ts +4 -4
- package/dist/umd/data-structure-typed.js +31196 -14608
- package/dist/umd/data-structure-typed.min.js +11 -5
- package/docs-site-docusaurus/README.md +41 -0
- package/docs-site-docusaurus/docs/api/README.md +52 -0
- package/docs-site-docusaurus/docs/api/classes/AVLTree.md +6644 -0
- package/docs-site-docusaurus/docs/api/classes/AVLTreeNode.md +282 -0
- package/docs-site-docusaurus/docs/api/classes/AbstractGraph.md +2266 -0
- package/docs-site-docusaurus/docs/api/classes/BST.md +6293 -0
- package/docs-site-docusaurus/docs/api/classes/BSTNode.md +333 -0
- package/docs-site-docusaurus/docs/api/classes/BinaryIndexedTree.md +455 -0
- package/docs-site-docusaurus/docs/api/classes/BinaryTree.md +4647 -0
- package/docs-site-docusaurus/docs/api/classes/BinaryTreeNode.md +331 -0
- package/docs-site-docusaurus/docs/api/classes/Deque.md +2767 -0
- package/docs-site-docusaurus/docs/api/classes/DirectedGraph.md +2999 -0
- package/docs-site-docusaurus/docs/api/classes/DoublyLinkedList.md +2685 -0
- package/docs-site-docusaurus/docs/api/classes/DoublyLinkedListNode.md +221 -0
- package/docs-site-docusaurus/docs/api/classes/FibonacciHeap.md +253 -0
- package/docs-site-docusaurus/docs/api/classes/FibonacciHeapNode.md +21 -0
- package/docs-site-docusaurus/docs/api/classes/HashMap.md +1333 -0
- package/docs-site-docusaurus/docs/api/classes/Heap.md +1881 -0
- package/docs-site-docusaurus/docs/api/classes/IterableElementBase.md +800 -0
- package/docs-site-docusaurus/docs/api/classes/IterableEntryBase.md +644 -0
- package/docs-site-docusaurus/docs/api/classes/LinearBase.md +1632 -0
- package/docs-site-docusaurus/docs/api/classes/LinearLinkedBase.md +1853 -0
- package/docs-site-docusaurus/docs/api/classes/LinkedHashMap.md +1108 -0
- package/docs-site-docusaurus/docs/api/classes/LinkedListNode.md +156 -0
- package/docs-site-docusaurus/docs/api/classes/LinkedListQueue.md +2824 -0
- package/docs-site-docusaurus/docs/api/classes/MapGraph.md +2929 -0
- package/docs-site-docusaurus/docs/api/classes/Matrix.md +1026 -0
- package/docs-site-docusaurus/docs/api/classes/MaxHeap.md +1866 -0
- package/docs-site-docusaurus/docs/api/classes/MaxPriorityQueue.md +1883 -0
- package/docs-site-docusaurus/docs/api/classes/MinHeap.md +1879 -0
- package/docs-site-docusaurus/docs/api/classes/MinPriorityQueue.md +1882 -0
- package/docs-site-docusaurus/docs/api/classes/Navigator.md +109 -0
- package/docs-site-docusaurus/docs/api/classes/PriorityQueue.md +1839 -0
- package/docs-site-docusaurus/docs/api/classes/Queue.md +2244 -0
- package/docs-site-docusaurus/docs/api/classes/RedBlackTree.md +6888 -0
- package/docs-site-docusaurus/docs/api/classes/SegmentTree.md +372 -0
- package/docs-site-docusaurus/docs/api/classes/SinglyLinkedList.md +2897 -0
- package/docs-site-docusaurus/docs/api/classes/SinglyLinkedListNode.md +169 -0
- package/docs-site-docusaurus/docs/api/classes/SkipList.md +1229 -0
- package/docs-site-docusaurus/docs/api/classes/Stack.md +1573 -0
- package/docs-site-docusaurus/docs/api/classes/TreeMap.md +1389 -0
- package/docs-site-docusaurus/docs/api/classes/TreeMultiMap.md +1591 -0
- package/docs-site-docusaurus/docs/api/classes/TreeSet.md +1246 -0
- package/docs-site-docusaurus/docs/api/classes/Trie.md +1708 -0
- package/docs-site-docusaurus/docs/api/classes/TrieNode.md +199 -0
- package/docs-site-docusaurus/docs/api/classes/UndirectedGraph.md +2979 -0
- package/docs-site-docusaurus/docs/guide/_category_.json +6 -0
- package/docs-site-docusaurus/docs/guide/architecture.md +615 -0
- package/docs-site-docusaurus/docs/guide/concepts.md +451 -0
- package/docs-site-docusaurus/docs/guide/faq.md +180 -0
- package/docs-site-docusaurus/docs/guide/guides.md +597 -0
- package/docs-site-docusaurus/docs/guide/installation.md +62 -0
- package/docs-site-docusaurus/docs/guide/integrations.md +825 -0
- package/docs-site-docusaurus/docs/guide/overview.md +645 -0
- package/docs-site-docusaurus/docs/guide/performance.md +835 -0
- package/docs-site-docusaurus/docs/guide/quick-start.md +104 -0
- package/docs-site-docusaurus/docs/guide/use-cases/_category_.json +6 -0
- package/docs-site-docusaurus/docs/guide/use-cases/array-sort-alternative.md +158 -0
- package/docs-site-docusaurus/docs/guide/use-cases/heap-vs-sorting.md +92 -0
- package/docs-site-docusaurus/docs/guide/use-cases/map-vs-treemap.md +151 -0
- package/docs-site-docusaurus/docs/guide/use-cases/priority-queue-typescript.md +113 -0
- package/docs-site-docusaurus/docs/guide/use-cases/treemap-javascript.md +151 -0
- package/docs-site-docusaurus/docusaurus.config.ts +159 -0
- package/docs-site-docusaurus/fix-mdx-generics.mjs +75 -0
- package/docs-site-docusaurus/package-lock.json +18667 -0
- package/docs-site-docusaurus/package.json +50 -0
- package/docs-site-docusaurus/prefix-class-to-methods.mjs +48 -0
- package/docs-site-docusaurus/sidebars.ts +23 -0
- package/docs-site-docusaurus/sort-protected.mjs +87 -0
- package/docs-site-docusaurus/src/css/custom.css +96 -0
- package/docs-site-docusaurus/src/pages/index.module.css +13 -0
- package/docs-site-docusaurus/src/pages/index.tsx +120 -0
- package/docs-site-docusaurus/src/pages/markdown-page.md +7 -0
- package/docs-site-docusaurus/src/theme/TOCItems/index.tsx +34 -0
- package/docs-site-docusaurus/static/.nojekyll +0 -0
- package/docs-site-docusaurus/static/img/docusaurus-social-card.jpg +0 -0
- package/docs-site-docusaurus/static/img/docusaurus.png +0 -0
- package/docs-site-docusaurus/static/img/favicon.ico +0 -0
- package/docs-site-docusaurus/static/img/favicon.png +0 -0
- package/docs-site-docusaurus/static/img/logo-180.png +0 -0
- package/docs-site-docusaurus/static/img/logo.jpg +0 -0
- package/docs-site-docusaurus/static/img/logo.png +0 -0
- package/docs-site-docusaurus/static/img/logo.svg +1 -0
- package/docs-site-docusaurus/static/img/og-image.png +0 -0
- package/docs-site-docusaurus/static/img/undraw_docusaurus_mountain.svg +171 -0
- package/docs-site-docusaurus/static/img/undraw_docusaurus_react.svg +170 -0
- package/docs-site-docusaurus/static/img/undraw_docusaurus_tree.svg +40 -0
- package/docs-site-docusaurus/static/llms.txt +37 -0
- package/docs-site-docusaurus/static/robots.txt +4 -0
- package/docs-site-docusaurus/typedoc.json +23 -0
- package/llms.txt +37 -0
- package/package.json +159 -55
- package/src/common/error.ts +19 -1
- package/src/common/index.ts +1 -1
- package/src/data-structures/base/index.ts +1 -0
- package/src/data-structures/base/iterable-element-base.ts +3 -2
- package/src/data-structures/base/iterable-entry-base.ts +8 -8
- package/src/data-structures/base/linear-base.ts +3 -3
- package/src/data-structures/binary-tree/avl-tree.ts +287 -0
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +327 -5
- package/src/data-structures/binary-tree/binary-tree.ts +581 -6
- package/src/data-structures/binary-tree/bst.ts +922 -7
- package/src/data-structures/binary-tree/red-black-tree.ts +453 -0
- package/src/data-structures/binary-tree/segment-tree.ts +139 -2
- package/src/data-structures/binary-tree/tree-map.ts +3300 -495
- package/src/data-structures/binary-tree/tree-multi-map.ts +3384 -563
- package/src/data-structures/binary-tree/tree-multi-set.ts +2757 -493
- package/src/data-structures/binary-tree/tree-set.ts +3122 -440
- package/src/data-structures/graph/abstract-graph.ts +6 -6
- package/src/data-structures/graph/directed-graph.ts +230 -0
- package/src/data-structures/graph/undirected-graph.ts +207 -0
- package/src/data-structures/hash/hash-map.ts +270 -19
- package/src/data-structures/heap/heap.ts +326 -4
- package/src/data-structures/heap/max-heap.ts +2 -2
- package/src/data-structures/linked-list/doubly-linked-list.ts +394 -3
- package/src/data-structures/linked-list/singly-linked-list.ts +348 -3
- package/src/data-structures/linked-list/skip-linked-list.ts +421 -7
- package/src/data-structures/matrix/matrix.ts +194 -10
- package/src/data-structures/priority-queue/max-priority-queue.ts +2 -2
- package/src/data-structures/queue/deque.ts +350 -5
- package/src/data-structures/queue/queue.ts +276 -0
- package/src/data-structures/stack/stack.ts +230 -0
- package/src/data-structures/trie/trie.ts +283 -7
- package/src/interfaces/graph.ts +1 -1
- package/src/types/common.ts +2 -2
- package/src/types/data-structures/binary-tree/bst.ts +1 -0
- package/src/types/data-structures/binary-tree/tree-map.ts +6 -0
- package/src/types/data-structures/binary-tree/tree-multi-set.ts +5 -0
- package/src/types/data-structures/binary-tree/tree-set.ts +5 -0
- package/src/types/data-structures/heap/heap.ts +1 -0
- package/src/types/data-structures/priority-queue/priority-queue.ts +1 -0
- package/src/types/utils/validate-type.ts +4 -4
- package/vercel.json +6 -0
- package/dist/leetcode/avl-tree-counter.mjs +0 -2957
- package/dist/leetcode/avl-tree-multi-map.mjs +0 -2889
- package/dist/leetcode/avl-tree.mjs +0 -2720
- package/dist/leetcode/binary-tree.mjs +0 -1594
- package/dist/leetcode/bst.mjs +0 -2398
- package/dist/leetcode/deque.mjs +0 -683
- package/dist/leetcode/directed-graph.mjs +0 -1733
- package/dist/leetcode/doubly-linked-list.mjs +0 -709
- package/dist/leetcode/hash-map.mjs +0 -493
- package/dist/leetcode/heap.mjs +0 -542
- package/dist/leetcode/max-heap.mjs +0 -375
- package/dist/leetcode/max-priority-queue.mjs +0 -383
- package/dist/leetcode/min-heap.mjs +0 -363
- package/dist/leetcode/min-priority-queue.mjs +0 -371
- package/dist/leetcode/priority-queue.mjs +0 -363
- package/dist/leetcode/queue.mjs +0 -943
- package/dist/leetcode/red-black-tree.mjs +0 -2765
- package/dist/leetcode/singly-linked-list.mjs +0 -754
- package/dist/leetcode/stack.mjs +0 -217
- package/dist/leetcode/tree-counter.mjs +0 -3039
- package/dist/leetcode/tree-multi-map.mjs +0 -2913
- package/dist/leetcode/trie.mjs +0 -413
- package/dist/leetcode/undirected-graph.mjs +0 -1650
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { Comparator, TreeMultiMapOptions } from '../../types';
|
|
10
|
-
import { ERR, Range } from '../../common';
|
|
10
|
+
import { ERR, raise, Range } from '../../common';
|
|
11
11
|
import { RedBlackTree, RedBlackTreeNode } from './red-black-tree';
|
|
12
12
|
import { TreeSet } from './tree-set';
|
|
13
13
|
|
|
@@ -49,7 +49,7 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
49
49
|
const comparator = options.comparator ?? TreeSet.createDefaultComparator<K>();
|
|
50
50
|
this.#isDefaultComparator = options.comparator === undefined;
|
|
51
51
|
const toEntryFn = options.toEntryFn;
|
|
52
|
-
this.#core = new RedBlackTree<K, V[], R>([], { ...options, comparator, isMapMode: options.isMapMode });
|
|
52
|
+
this.#core = new RedBlackTree<K, V[], R>([], { ...options, comparator, isMapMode: options.isMapMode, enableOrderStatistic: options.enableOrderStatistic });
|
|
53
53
|
|
|
54
54
|
for (const x of keysNodesEntriesOrRaws) {
|
|
55
55
|
if (x === null || x === undefined) continue;
|
|
@@ -91,15 +91,15 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
91
91
|
// reuse TreeSet strict validation (same policy)
|
|
92
92
|
// NOTE: TreeSet._validateKey is private, so we replicate the checks.
|
|
93
93
|
if (typeof key === 'number') {
|
|
94
|
-
if (Number.isNaN(key))
|
|
94
|
+
if (Number.isNaN(key)) raise(TypeError, ERR.invalidNaN('TreeMultiMap'));
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
97
|
if (typeof key === 'string') return;
|
|
98
98
|
if (key instanceof Date) {
|
|
99
|
-
if (Number.isNaN(key.getTime()))
|
|
99
|
+
if (Number.isNaN(key.getTime())) raise(TypeError, ERR.invalidDate('TreeMultiMap'));
|
|
100
100
|
return;
|
|
101
101
|
}
|
|
102
|
-
|
|
102
|
+
raise(TypeError, ERR.comparatorRequired('TreeMultiMap'));
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
/**
|
|
@@ -156,17 +156,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
156
156
|
|
|
157
157
|
|
|
158
158
|
|
|
159
|
-
* @example
|
|
160
|
-
* // Check if empty
|
|
161
|
-
* console.log(new TreeMultiMap().isEmpty()); // true;
|
|
162
|
-
*/
|
|
163
|
-
isEmpty(): boolean {
|
|
164
|
-
return this.size === 0;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Removes all entries from the map.
|
|
169
|
-
* @remarks Time O(1), Space O(1)
|
|
170
159
|
|
|
171
160
|
|
|
172
161
|
|
|
@@ -210,58 +199,20 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
210
199
|
|
|
211
200
|
|
|
212
201
|
|
|
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;
|
|
219
|
-
*/
|
|
220
|
-
clear(): void {
|
|
221
|
-
this.#core.clear();
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Bucket length for a key (missing => 0).
|
|
226
|
-
* @remarks Time O(log n), Space O(1)
|
|
227
202
|
|
|
228
203
|
|
|
229
204
|
|
|
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;
|
|
236
|
-
*/
|
|
237
|
-
count(key: K): number {
|
|
238
|
-
const b = this.get(key);
|
|
239
|
-
return Array.isArray(b) ? b.length : 0;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Total number of values across all buckets (Σ bucket.length).
|
|
244
|
-
* @remarks Time O(n), Space O(1)
|
|
245
205
|
|
|
246
206
|
|
|
247
207
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
get totalSize(): number {
|
|
257
|
-
let sum = 0;
|
|
258
|
-
for (const [, bucket] of this) sum += bucket.length;
|
|
259
|
-
return sum;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Whether the map contains the given key.
|
|
264
|
-
* @remarks Time O(log n), Space O(1)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
|
|
265
216
|
|
|
266
217
|
|
|
267
218
|
|
|
@@ -321,20 +272,23 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
321
272
|
|
|
322
273
|
|
|
323
274
|
* @example
|
|
324
|
-
* // Check
|
|
325
|
-
*
|
|
326
|
-
* mm.add(1, 'a');
|
|
327
|
-
* console.log(mm.has(1)); // true;
|
|
328
|
-
* console.log(mm.has(2)); // false;
|
|
275
|
+
* // Check if empty
|
|
276
|
+
* console.log(new TreeMultiMap().isEmpty()); // true;
|
|
329
277
|
*/
|
|
330
|
-
|
|
331
|
-
this.
|
|
332
|
-
return this.#core.has(key);
|
|
278
|
+
isEmpty(): boolean {
|
|
279
|
+
return this.size === 0;
|
|
333
280
|
}
|
|
334
281
|
|
|
335
282
|
/**
|
|
336
|
-
*
|
|
337
|
-
* @remarks Time O(
|
|
283
|
+
* Removes all entries from the map.
|
|
284
|
+
* @remarks Time O(1), Space O(1)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
|
|
338
292
|
|
|
339
293
|
|
|
340
294
|
|
|
@@ -393,21 +347,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
393
347
|
|
|
394
348
|
|
|
395
349
|
|
|
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'];
|
|
402
|
-
*/
|
|
403
|
-
get(key: K): V[] | undefined {
|
|
404
|
-
this._validateKey(key);
|
|
405
|
-
return this.#core.get(key);
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/**
|
|
409
|
-
* Append a single value.
|
|
410
|
-
* @remarks Time O(log n), Space O(1)
|
|
411
350
|
|
|
412
351
|
|
|
413
352
|
|
|
@@ -445,27 +384,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
445
384
|
|
|
446
385
|
|
|
447
386
|
|
|
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'];
|
|
455
|
-
*/
|
|
456
|
-
add(key: K, value: V): boolean {
|
|
457
|
-
this._validateKey(key);
|
|
458
|
-
const bucket = this.#core.get(key);
|
|
459
|
-
if (bucket) {
|
|
460
|
-
bucket.push(value);
|
|
461
|
-
return true;
|
|
462
|
-
}
|
|
463
|
-
return this.#core.set(key, [value]);
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
/**
|
|
467
|
-
* Alias for compatibility with existing TreeMultiMap semantics.
|
|
468
|
-
* @remarks Time O(log n), Space O(1) for single value; O(log n + m) for bucket append
|
|
469
387
|
|
|
470
388
|
|
|
471
389
|
|
|
@@ -523,39 +441,18 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
523
441
|
|
|
524
442
|
|
|
525
443
|
* @example
|
|
526
|
-
* //
|
|
444
|
+
* // Remove all entries
|
|
527
445
|
* const mm = new TreeMultiMap<number, string>();
|
|
528
|
-
* mm.
|
|
529
|
-
* mm.
|
|
530
|
-
* console.log(mm.
|
|
446
|
+
* mm.add(1, 'a');
|
|
447
|
+
* mm.clear();
|
|
448
|
+
* console.log(mm.isEmpty()); // true;
|
|
531
449
|
*/
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
set(entry: [K | null | undefined, V[] | undefined] | K | null | undefined, value?: V): boolean {
|
|
535
|
-
if (entry === null || entry === undefined) return false;
|
|
536
|
-
if (Array.isArray(entry)) {
|
|
537
|
-
const [k, bucket] = entry;
|
|
538
|
-
if (k === null || k === undefined) return false;
|
|
539
|
-
if (value !== undefined) return this.add(k as K, value);
|
|
540
|
-
if (bucket === undefined) {
|
|
541
|
-
// ensure key exists
|
|
542
|
-
return this.#core.set(k as K, [] as V[]);
|
|
543
|
-
}
|
|
544
|
-
// append bucket
|
|
545
|
-
const existing = this.#core.get(k as K);
|
|
546
|
-
if (existing) {
|
|
547
|
-
existing.push(...bucket);
|
|
548
|
-
return true;
|
|
549
|
-
}
|
|
550
|
-
return this.#core.set(k as K, [...bucket] as V[]);
|
|
551
|
-
}
|
|
552
|
-
// key-only or key+value
|
|
553
|
-
if (value !== undefined) return this.add(entry as K, value);
|
|
554
|
-
return this.#core.set(entry as K, [] as V[]);
|
|
450
|
+
clear(): void {
|
|
451
|
+
this.#core.clear();
|
|
555
452
|
}
|
|
556
453
|
|
|
557
454
|
/**
|
|
558
|
-
*
|
|
455
|
+
* Bucket length for a key (missing => 0).
|
|
559
456
|
* @remarks Time O(log n), Space O(1)
|
|
560
457
|
|
|
561
458
|
|
|
@@ -583,12 +480,21 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
583
480
|
|
|
584
481
|
|
|
585
482
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
483
|
+
* @example
|
|
484
|
+
* // Count values for key
|
|
485
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
486
|
+
* mm.add(1, 'a');
|
|
487
|
+
* mm.add(1, 'b');
|
|
488
|
+
* console.log(mm.count(1)); // 2;
|
|
489
|
+
*/
|
|
490
|
+
count(key: K): number {
|
|
491
|
+
const b = this.get(key);
|
|
492
|
+
return Array.isArray(b) ? b.length : 0;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Total number of values across all buckets (Σ bucket.length).
|
|
497
|
+
* @remarks Time O(n), Space O(1)
|
|
592
498
|
|
|
593
499
|
|
|
594
500
|
|
|
@@ -616,106 +522,3174 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
616
522
|
|
|
617
523
|
|
|
618
524
|
* @example
|
|
619
|
-
* //
|
|
525
|
+
* // Total number of values
|
|
620
526
|
* const mm = new TreeMultiMap<number, string>();
|
|
621
527
|
* mm.add(1, 'a');
|
|
622
|
-
* mm.add(
|
|
623
|
-
* mm.
|
|
624
|
-
* console.log(mm.
|
|
528
|
+
* mm.add(1, 'b');
|
|
529
|
+
* mm.add(2, 'c');
|
|
530
|
+
* console.log(mm.totalSize); // 3;
|
|
625
531
|
*/
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
532
|
+
get totalSize(): number {
|
|
533
|
+
let sum = 0;
|
|
534
|
+
for (const [, bucket] of this) sum += bucket.length;
|
|
535
|
+
return sum;
|
|
629
536
|
}
|
|
630
537
|
|
|
631
538
|
/**
|
|
632
|
-
*
|
|
633
|
-
* @remarks Time O(log n
|
|
539
|
+
* Whether the map contains the given key.
|
|
540
|
+
* @remarks Time O(log n), Space O(1)
|
|
634
541
|
|
|
635
542
|
|
|
636
543
|
|
|
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;
|
|
643
|
-
*/
|
|
644
|
-
hasEntry(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): boolean {
|
|
645
|
-
const bucket = this.get(key);
|
|
646
|
-
if (!Array.isArray(bucket)) return false;
|
|
647
|
-
return bucket.some(v => eq(v, value));
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
/**
|
|
651
|
-
* Delete a single occurrence of a value from a key's bucket.
|
|
652
|
-
* @remarks Time O(log n + m), Space O(1) where m is bucket size
|
|
653
544
|
|
|
654
545
|
|
|
655
546
|
|
|
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'];
|
|
663
|
-
*/
|
|
664
|
-
deleteValue(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): boolean {
|
|
665
|
-
const bucket = this.get(key);
|
|
666
|
-
if (!Array.isArray(bucket)) return false;
|
|
667
|
-
const idx = bucket.findIndex(v => eq(v, value));
|
|
668
|
-
if (idx === -1) return false;
|
|
669
|
-
bucket.splice(idx, 1);
|
|
670
|
-
if (bucket.length === 0) this.delete(key);
|
|
671
|
-
return true;
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
/**
|
|
675
|
-
* Delete all occurrences of a value from a key's bucket.
|
|
676
|
-
* @remarks Time O(log n + m), Space O(1) where m is bucket size
|
|
677
547
|
|
|
678
548
|
|
|
679
549
|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
|
|
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
|
+
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
|
|
671
|
+
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
|
|
709
|
+
|
|
710
|
+
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
|
|
718
|
+
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
|
|
724
|
+
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
|
|
730
|
+
|
|
731
|
+
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
* @example
|
|
738
|
+
* // Check key existence
|
|
739
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
740
|
+
* mm.add(1, 'a');
|
|
741
|
+
* console.log(mm.has(1)); // true;
|
|
742
|
+
* console.log(mm.has(2)); // false;
|
|
743
|
+
*/
|
|
744
|
+
has(key: K): boolean {
|
|
745
|
+
this._validateKey(key);
|
|
746
|
+
return this.#core.has(key);
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* Live bucket reference (do not auto-delete key if bucket becomes empty via mutation).
|
|
751
|
+
* @remarks Time O(log n), Space O(1)
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
|
|
758
|
+
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
|
|
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
|
+
|
|
820
|
+
|
|
821
|
+
|
|
822
|
+
|
|
823
|
+
|
|
824
|
+
|
|
825
|
+
|
|
826
|
+
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
|
|
830
|
+
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
|
|
844
|
+
|
|
845
|
+
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
|
|
853
|
+
|
|
854
|
+
|
|
855
|
+
|
|
856
|
+
|
|
857
|
+
|
|
858
|
+
|
|
859
|
+
|
|
860
|
+
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
|
|
867
|
+
|
|
868
|
+
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
|
|
872
|
+
|
|
873
|
+
|
|
874
|
+
|
|
875
|
+
|
|
876
|
+
|
|
877
|
+
|
|
878
|
+
|
|
879
|
+
|
|
880
|
+
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
|
|
886
|
+
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
|
|
891
|
+
|
|
892
|
+
|
|
893
|
+
|
|
894
|
+
|
|
895
|
+
|
|
896
|
+
|
|
897
|
+
|
|
898
|
+
|
|
899
|
+
|
|
900
|
+
|
|
901
|
+
|
|
902
|
+
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
|
|
907
|
+
|
|
908
|
+
|
|
909
|
+
|
|
910
|
+
|
|
911
|
+
|
|
912
|
+
|
|
913
|
+
|
|
914
|
+
|
|
915
|
+
|
|
916
|
+
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
|
|
925
|
+
|
|
926
|
+
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
|
|
932
|
+
|
|
933
|
+
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
|
|
944
|
+
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
|
|
948
|
+
* @example
|
|
949
|
+
* // Get values for key
|
|
950
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
951
|
+
* mm.add(1, 'a');
|
|
952
|
+
* mm.add(1, 'b');
|
|
953
|
+
* console.log(mm.get(1)); // ['a', 'b'];
|
|
954
|
+
*/
|
|
955
|
+
get(key: K): V[] | undefined {
|
|
956
|
+
this._validateKey(key);
|
|
957
|
+
return this.#core.get(key);
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
/**
|
|
961
|
+
* Append a single value.
|
|
962
|
+
* @remarks Time O(log n), Space O(1)
|
|
963
|
+
|
|
964
|
+
|
|
965
|
+
|
|
966
|
+
|
|
967
|
+
|
|
968
|
+
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
|
|
975
|
+
|
|
976
|
+
|
|
977
|
+
|
|
978
|
+
|
|
979
|
+
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
|
|
991
|
+
|
|
992
|
+
|
|
993
|
+
|
|
994
|
+
|
|
995
|
+
|
|
996
|
+
|
|
997
|
+
|
|
998
|
+
|
|
999
|
+
|
|
1000
|
+
|
|
1001
|
+
|
|
1002
|
+
|
|
1003
|
+
|
|
1004
|
+
|
|
1005
|
+
|
|
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
|
+
|
|
1053
|
+
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
|
|
1058
|
+
|
|
1059
|
+
|
|
1060
|
+
|
|
1061
|
+
|
|
1062
|
+
|
|
1063
|
+
|
|
1064
|
+
|
|
1065
|
+
|
|
1066
|
+
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
|
|
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
|
+
* @example
|
|
1116
|
+
* // Add key-value pair
|
|
1117
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1118
|
+
* mm.add(1, 'a');
|
|
1119
|
+
* mm.add(1, 'b');
|
|
1120
|
+
* mm.add(2, 'c');
|
|
1121
|
+
* console.log(mm.get(1)); // ['a', 'b'];
|
|
1122
|
+
*/
|
|
1123
|
+
add(key: K, value: V): boolean {
|
|
1124
|
+
this._validateKey(key);
|
|
1125
|
+
const bucket = this.#core.get(key);
|
|
1126
|
+
if (bucket) {
|
|
1127
|
+
bucket.push(value);
|
|
1128
|
+
return true;
|
|
1129
|
+
}
|
|
1130
|
+
return this.#core.set(key, [value]);
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
/**
|
|
1134
|
+
* Alias for compatibility with existing TreeMultiMap semantics.
|
|
1135
|
+
* @remarks Time O(log n), Space O(1) for single value; O(log n + m) for bucket append
|
|
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
|
+
|
|
1171
|
+
|
|
1172
|
+
|
|
1173
|
+
|
|
1174
|
+
|
|
1175
|
+
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
|
|
1179
|
+
|
|
1180
|
+
|
|
1181
|
+
|
|
1182
|
+
|
|
1183
|
+
|
|
1184
|
+
|
|
1185
|
+
|
|
1186
|
+
|
|
1187
|
+
|
|
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
|
+
|
|
1223
|
+
|
|
1224
|
+
|
|
1225
|
+
|
|
1226
|
+
|
|
1227
|
+
|
|
1228
|
+
|
|
1229
|
+
|
|
1230
|
+
|
|
1231
|
+
|
|
1232
|
+
|
|
1233
|
+
|
|
1234
|
+
|
|
1235
|
+
|
|
1236
|
+
|
|
1237
|
+
|
|
1238
|
+
|
|
1239
|
+
|
|
1240
|
+
|
|
1241
|
+
|
|
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
|
+
|
|
1286
|
+
|
|
1287
|
+
|
|
1288
|
+
|
|
1289
|
+
|
|
1290
|
+
|
|
1291
|
+
|
|
1292
|
+
|
|
1293
|
+
|
|
1294
|
+
|
|
1295
|
+
|
|
1296
|
+
|
|
1297
|
+
|
|
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
|
+
* @example
|
|
1331
|
+
* // Set values for key
|
|
1332
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1333
|
+
* mm.set(1, 'a');
|
|
1334
|
+
* mm.set(1, 'b');
|
|
1335
|
+
* console.log(mm.get(1)); // ['a', 'b'];
|
|
1336
|
+
*/
|
|
1337
|
+
set(entry: [K | null | undefined, V[] | undefined] | K | null | undefined, value?: V): boolean;
|
|
1338
|
+
set(key: K, value: V): boolean;
|
|
1339
|
+
set(entry: [K | null | undefined, V[] | undefined] | K | null | undefined, value?: V): boolean {
|
|
1340
|
+
if (entry === null || entry === undefined) return false;
|
|
1341
|
+
if (Array.isArray(entry)) {
|
|
1342
|
+
const [k, bucket] = entry;
|
|
1343
|
+
if (k === null || k === undefined) return false;
|
|
1344
|
+
if (value !== undefined) return this.add(k as K, value);
|
|
1345
|
+
if (bucket === undefined) {
|
|
1346
|
+
// ensure key exists
|
|
1347
|
+
return this.#core.set(k as K, [] as V[]);
|
|
1348
|
+
}
|
|
1349
|
+
// append bucket
|
|
1350
|
+
const existing = this.#core.get(k as K);
|
|
1351
|
+
if (existing) {
|
|
1352
|
+
existing.push(...bucket);
|
|
1353
|
+
return true;
|
|
1354
|
+
}
|
|
1355
|
+
return this.#core.set(k as K, [...bucket] as V[]);
|
|
1356
|
+
}
|
|
1357
|
+
// key-only or key+value
|
|
1358
|
+
if (value !== undefined) return this.add(entry as K, value);
|
|
1359
|
+
return this.#core.set(entry as K, [] as V[]);
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
/**
|
|
1363
|
+
* Deletes a key and its entire bucket.
|
|
1364
|
+
* @remarks Time O(log n), Space O(1)
|
|
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
|
+
|
|
1403
|
+
|
|
1404
|
+
|
|
1405
|
+
|
|
1406
|
+
|
|
1407
|
+
|
|
1408
|
+
|
|
1409
|
+
|
|
1410
|
+
|
|
1411
|
+
|
|
1412
|
+
|
|
1413
|
+
|
|
1414
|
+
|
|
1415
|
+
|
|
1416
|
+
|
|
1417
|
+
|
|
1418
|
+
|
|
1419
|
+
|
|
1420
|
+
|
|
1421
|
+
|
|
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
|
+
|
|
1466
|
+
|
|
1467
|
+
|
|
1468
|
+
|
|
1469
|
+
|
|
1470
|
+
|
|
1471
|
+
|
|
1472
|
+
|
|
1473
|
+
|
|
1474
|
+
|
|
1475
|
+
|
|
1476
|
+
|
|
1477
|
+
|
|
1478
|
+
|
|
1479
|
+
|
|
1480
|
+
|
|
1481
|
+
|
|
1482
|
+
|
|
1483
|
+
|
|
1484
|
+
|
|
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
|
+
|
|
1529
|
+
|
|
1530
|
+
|
|
1531
|
+
|
|
1532
|
+
|
|
1533
|
+
|
|
1534
|
+
|
|
1535
|
+
|
|
1536
|
+
|
|
1537
|
+
|
|
1538
|
+
|
|
1539
|
+
|
|
1540
|
+
|
|
1541
|
+
|
|
1542
|
+
|
|
1543
|
+
|
|
1544
|
+
|
|
1545
|
+
|
|
1546
|
+
|
|
1547
|
+
|
|
1548
|
+
|
|
1549
|
+
|
|
1550
|
+
|
|
1551
|
+
|
|
1552
|
+
|
|
1553
|
+
|
|
1554
|
+
|
|
1555
|
+
|
|
1556
|
+
|
|
1557
|
+
|
|
1558
|
+
|
|
1559
|
+
|
|
1560
|
+
|
|
1561
|
+
* @example
|
|
1562
|
+
* // Remove key
|
|
1563
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1564
|
+
* mm.add(1, 'a');
|
|
1565
|
+
* mm.add(2, 'b');
|
|
1566
|
+
* mm.delete(1);
|
|
1567
|
+
* console.log(mm.has(1)); // false;
|
|
1568
|
+
*/
|
|
1569
|
+
delete(key: K): boolean {
|
|
1570
|
+
this._validateKey(key);
|
|
1571
|
+
return this.#core.delete(key).length > 0;
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
/**
|
|
1575
|
+
* Check if a specific value exists in a key's bucket.
|
|
1576
|
+
* @remarks Time O(log n + m), Space O(1) where m is bucket size
|
|
1577
|
+
|
|
1578
|
+
|
|
1579
|
+
|
|
1580
|
+
|
|
1581
|
+
|
|
1582
|
+
|
|
1583
|
+
|
|
1584
|
+
|
|
1585
|
+
|
|
1586
|
+
|
|
1587
|
+
|
|
1588
|
+
|
|
1589
|
+
|
|
1590
|
+
|
|
1591
|
+
|
|
1592
|
+
|
|
1593
|
+
|
|
1594
|
+
|
|
1595
|
+
|
|
1596
|
+
|
|
1597
|
+
|
|
1598
|
+
|
|
1599
|
+
|
|
1600
|
+
|
|
1601
|
+
|
|
1602
|
+
|
|
1603
|
+
* @example
|
|
1604
|
+
* // Check specific key-value
|
|
1605
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1606
|
+
* mm.add(1, 'a');
|
|
1607
|
+
* console.log(mm.hasEntry(1, 'a')); // true;
|
|
1608
|
+
* console.log(mm.hasEntry(1, 'z')); // false;
|
|
1609
|
+
*/
|
|
1610
|
+
hasEntry(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): boolean {
|
|
1611
|
+
const bucket = this.get(key);
|
|
1612
|
+
if (!Array.isArray(bucket)) return false;
|
|
1613
|
+
return bucket.some(v => eq(v, value));
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
/**
|
|
1617
|
+
* Delete a single occurrence of a value from a key's bucket.
|
|
1618
|
+
* @remarks Time O(log n + m), Space O(1) where m is bucket size
|
|
1619
|
+
|
|
1620
|
+
|
|
1621
|
+
|
|
1622
|
+
|
|
1623
|
+
|
|
1624
|
+
|
|
1625
|
+
|
|
1626
|
+
|
|
1627
|
+
|
|
1628
|
+
|
|
1629
|
+
|
|
1630
|
+
|
|
1631
|
+
|
|
1632
|
+
|
|
1633
|
+
|
|
1634
|
+
|
|
1635
|
+
|
|
1636
|
+
|
|
1637
|
+
|
|
1638
|
+
|
|
1639
|
+
|
|
1640
|
+
|
|
1641
|
+
|
|
1642
|
+
|
|
1643
|
+
|
|
1644
|
+
|
|
1645
|
+
* @example
|
|
1646
|
+
* // Delete specific value
|
|
1647
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1648
|
+
* mm.add(1, 'a');
|
|
1649
|
+
* mm.add(1, 'b');
|
|
1650
|
+
* mm.deleteValue(1, 'a');
|
|
1651
|
+
* console.log(mm.get(1)); // ['b'];
|
|
1652
|
+
*/
|
|
1653
|
+
deleteValue(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): boolean {
|
|
1654
|
+
const bucket = this.get(key);
|
|
1655
|
+
if (!Array.isArray(bucket)) return false;
|
|
1656
|
+
const idx = bucket.findIndex(v => eq(v, value));
|
|
1657
|
+
if (idx === -1) return false;
|
|
1658
|
+
bucket.splice(idx, 1);
|
|
1659
|
+
if (bucket.length === 0) this.delete(key);
|
|
1660
|
+
return true;
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
/**
|
|
1664
|
+
* Delete all occurrences of a value from a key's bucket.
|
|
1665
|
+
* @remarks Time O(log n + m), Space O(1) where m is bucket size
|
|
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
|
+
* @example
|
|
1693
|
+
* // Delete all matching values
|
|
1694
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1695
|
+
* mm.add(1, 'a');
|
|
1696
|
+
* mm.add(1, 'a');
|
|
1697
|
+
* mm.add(1, 'b');
|
|
1698
|
+
* const count = mm.deleteValues(1, 'a');
|
|
1699
|
+
* console.log(count); // 2;
|
|
1700
|
+
*/
|
|
1701
|
+
deleteValues(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): number {
|
|
1702
|
+
const bucket = this.get(key);
|
|
1703
|
+
if (!Array.isArray(bucket) || bucket.length === 0) return 0;
|
|
1704
|
+
let removed = 0;
|
|
1705
|
+
for (let i = bucket.length - 1; i >= 0; i--) {
|
|
1706
|
+
if (eq(bucket[i] as V, value)) {
|
|
1707
|
+
bucket.splice(i, 1);
|
|
1708
|
+
removed++;
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
if (bucket.length === 0 && removed > 0) this.delete(key);
|
|
700
1712
|
return removed;
|
|
701
1713
|
}
|
|
702
1714
|
|
|
703
|
-
// ---- iteration (bucket view) ----
|
|
704
|
-
|
|
1715
|
+
// ---- iteration (bucket view) ----
|
|
1716
|
+
|
|
1717
|
+
/**
|
|
1718
|
+
* Iterates over all entries as [key, bucket] pairs.
|
|
1719
|
+
* @remarks Time O(n), Space O(1)
|
|
1720
|
+
*/
|
|
1721
|
+
*[Symbol.iterator](): Iterator<[K, V[]]> {
|
|
1722
|
+
for (const [k, v] of this.#core) {
|
|
1723
|
+
// core always stores buckets, but guard anyway
|
|
1724
|
+
yield [k, v ?? /* istanbul ignore next */ ([] as V[])];
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
/**
|
|
1729
|
+
* Iterates over all keys.
|
|
1730
|
+
* @remarks Time O(n), Space O(1)
|
|
1731
|
+
|
|
1732
|
+
|
|
1733
|
+
|
|
1734
|
+
|
|
1735
|
+
|
|
1736
|
+
|
|
1737
|
+
|
|
1738
|
+
|
|
1739
|
+
|
|
1740
|
+
|
|
1741
|
+
|
|
1742
|
+
|
|
1743
|
+
|
|
1744
|
+
|
|
1745
|
+
|
|
1746
|
+
|
|
1747
|
+
|
|
1748
|
+
|
|
1749
|
+
|
|
1750
|
+
|
|
1751
|
+
|
|
1752
|
+
|
|
1753
|
+
|
|
1754
|
+
|
|
1755
|
+
|
|
1756
|
+
|
|
1757
|
+
|
|
1758
|
+
|
|
1759
|
+
|
|
1760
|
+
|
|
1761
|
+
|
|
1762
|
+
|
|
1763
|
+
|
|
1764
|
+
|
|
1765
|
+
|
|
1766
|
+
|
|
1767
|
+
|
|
1768
|
+
|
|
1769
|
+
|
|
1770
|
+
|
|
1771
|
+
|
|
1772
|
+
|
|
1773
|
+
|
|
1774
|
+
|
|
1775
|
+
|
|
1776
|
+
|
|
1777
|
+
|
|
1778
|
+
|
|
1779
|
+
|
|
1780
|
+
|
|
1781
|
+
|
|
1782
|
+
|
|
1783
|
+
|
|
1784
|
+
|
|
1785
|
+
|
|
1786
|
+
|
|
1787
|
+
|
|
1788
|
+
|
|
1789
|
+
|
|
1790
|
+
|
|
1791
|
+
|
|
1792
|
+
|
|
1793
|
+
|
|
1794
|
+
|
|
1795
|
+
|
|
1796
|
+
|
|
1797
|
+
|
|
1798
|
+
|
|
1799
|
+
|
|
1800
|
+
|
|
1801
|
+
|
|
1802
|
+
|
|
1803
|
+
|
|
1804
|
+
|
|
1805
|
+
|
|
1806
|
+
|
|
1807
|
+
|
|
1808
|
+
|
|
1809
|
+
|
|
1810
|
+
|
|
1811
|
+
|
|
1812
|
+
|
|
1813
|
+
|
|
1814
|
+
|
|
1815
|
+
|
|
1816
|
+
|
|
1817
|
+
|
|
1818
|
+
|
|
1819
|
+
|
|
1820
|
+
|
|
1821
|
+
|
|
1822
|
+
|
|
1823
|
+
|
|
1824
|
+
|
|
1825
|
+
|
|
1826
|
+
|
|
1827
|
+
|
|
1828
|
+
|
|
1829
|
+
|
|
1830
|
+
|
|
1831
|
+
|
|
1832
|
+
|
|
1833
|
+
|
|
1834
|
+
|
|
1835
|
+
|
|
1836
|
+
|
|
1837
|
+
|
|
1838
|
+
|
|
1839
|
+
|
|
1840
|
+
|
|
1841
|
+
|
|
1842
|
+
|
|
1843
|
+
|
|
1844
|
+
|
|
1845
|
+
|
|
1846
|
+
|
|
1847
|
+
|
|
1848
|
+
|
|
1849
|
+
|
|
1850
|
+
|
|
1851
|
+
|
|
1852
|
+
|
|
1853
|
+
|
|
1854
|
+
|
|
1855
|
+
|
|
1856
|
+
|
|
1857
|
+
|
|
1858
|
+
|
|
1859
|
+
|
|
1860
|
+
|
|
1861
|
+
|
|
1862
|
+
|
|
1863
|
+
|
|
1864
|
+
|
|
1865
|
+
|
|
1866
|
+
|
|
1867
|
+
|
|
1868
|
+
|
|
1869
|
+
|
|
1870
|
+
|
|
1871
|
+
|
|
1872
|
+
|
|
1873
|
+
|
|
1874
|
+
|
|
1875
|
+
|
|
1876
|
+
|
|
1877
|
+
|
|
1878
|
+
|
|
1879
|
+
|
|
1880
|
+
|
|
1881
|
+
|
|
1882
|
+
|
|
1883
|
+
|
|
1884
|
+
|
|
1885
|
+
|
|
1886
|
+
|
|
1887
|
+
|
|
1888
|
+
|
|
1889
|
+
* @example
|
|
1890
|
+
* // Iterate keys
|
|
1891
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
1892
|
+
* mm.add(3, 'c');
|
|
1893
|
+
* mm.add(1, 'a');
|
|
1894
|
+
* console.log([...mm.keys()]); // [1, 3];
|
|
1895
|
+
*/
|
|
1896
|
+
*keys(): IterableIterator<K> {
|
|
1897
|
+
yield* this.#core.keys();
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1900
|
+
/**
|
|
1901
|
+
* Iterates over all buckets.
|
|
1902
|
+
* @remarks Time O(n), Space O(1)
|
|
1903
|
+
|
|
1904
|
+
|
|
1905
|
+
|
|
1906
|
+
|
|
1907
|
+
|
|
1908
|
+
|
|
1909
|
+
|
|
1910
|
+
|
|
1911
|
+
|
|
1912
|
+
|
|
1913
|
+
|
|
1914
|
+
|
|
1915
|
+
|
|
1916
|
+
|
|
1917
|
+
|
|
1918
|
+
|
|
1919
|
+
|
|
1920
|
+
|
|
1921
|
+
|
|
1922
|
+
|
|
1923
|
+
|
|
1924
|
+
|
|
1925
|
+
|
|
1926
|
+
|
|
1927
|
+
|
|
1928
|
+
|
|
1929
|
+
|
|
1930
|
+
|
|
1931
|
+
|
|
1932
|
+
|
|
1933
|
+
|
|
1934
|
+
|
|
1935
|
+
|
|
1936
|
+
|
|
1937
|
+
|
|
1938
|
+
|
|
1939
|
+
|
|
1940
|
+
|
|
1941
|
+
|
|
1942
|
+
|
|
1943
|
+
|
|
1944
|
+
|
|
1945
|
+
|
|
1946
|
+
|
|
1947
|
+
|
|
1948
|
+
|
|
1949
|
+
|
|
1950
|
+
|
|
1951
|
+
|
|
1952
|
+
|
|
1953
|
+
|
|
1954
|
+
|
|
1955
|
+
|
|
1956
|
+
|
|
1957
|
+
|
|
1958
|
+
|
|
1959
|
+
|
|
1960
|
+
|
|
1961
|
+
|
|
1962
|
+
|
|
1963
|
+
|
|
1964
|
+
|
|
1965
|
+
|
|
1966
|
+
|
|
1967
|
+
|
|
1968
|
+
|
|
1969
|
+
|
|
1970
|
+
|
|
1971
|
+
|
|
1972
|
+
|
|
1973
|
+
|
|
1974
|
+
|
|
1975
|
+
|
|
1976
|
+
|
|
1977
|
+
|
|
1978
|
+
|
|
1979
|
+
|
|
1980
|
+
|
|
1981
|
+
|
|
1982
|
+
|
|
1983
|
+
|
|
1984
|
+
|
|
1985
|
+
|
|
1986
|
+
|
|
1987
|
+
|
|
1988
|
+
|
|
1989
|
+
|
|
1990
|
+
|
|
1991
|
+
|
|
1992
|
+
|
|
1993
|
+
|
|
1994
|
+
|
|
1995
|
+
|
|
1996
|
+
|
|
1997
|
+
|
|
1998
|
+
|
|
1999
|
+
|
|
2000
|
+
|
|
2001
|
+
|
|
2002
|
+
|
|
2003
|
+
|
|
2004
|
+
|
|
2005
|
+
|
|
2006
|
+
|
|
2007
|
+
|
|
2008
|
+
|
|
2009
|
+
|
|
2010
|
+
|
|
2011
|
+
|
|
2012
|
+
|
|
2013
|
+
|
|
2014
|
+
|
|
2015
|
+
|
|
2016
|
+
|
|
2017
|
+
|
|
2018
|
+
|
|
2019
|
+
|
|
2020
|
+
|
|
2021
|
+
|
|
2022
|
+
|
|
2023
|
+
|
|
2024
|
+
|
|
2025
|
+
|
|
2026
|
+
|
|
2027
|
+
|
|
2028
|
+
|
|
2029
|
+
|
|
2030
|
+
|
|
2031
|
+
|
|
2032
|
+
|
|
2033
|
+
|
|
2034
|
+
|
|
2035
|
+
|
|
2036
|
+
|
|
2037
|
+
|
|
2038
|
+
|
|
2039
|
+
|
|
2040
|
+
|
|
2041
|
+
|
|
2042
|
+
|
|
2043
|
+
|
|
2044
|
+
|
|
2045
|
+
|
|
2046
|
+
|
|
2047
|
+
|
|
2048
|
+
|
|
2049
|
+
|
|
2050
|
+
|
|
2051
|
+
|
|
2052
|
+
|
|
2053
|
+
|
|
2054
|
+
|
|
2055
|
+
|
|
2056
|
+
|
|
2057
|
+
|
|
2058
|
+
|
|
2059
|
+
|
|
2060
|
+
|
|
2061
|
+
* @example
|
|
2062
|
+
* // Iterate value arrays
|
|
2063
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
2064
|
+
* mm.add(1, 'a');
|
|
2065
|
+
* mm.add(1, 'b');
|
|
2066
|
+
* console.log([...mm.values()]); // [['a', 'b']];
|
|
2067
|
+
*/
|
|
2068
|
+
*values(): IterableIterator<V[]> {
|
|
2069
|
+
for (const [, bucket] of this) yield bucket;
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
// ---- entry-flat views ----
|
|
2073
|
+
|
|
2074
|
+
/**
|
|
2075
|
+
* Iterates over all entries for a specific key.
|
|
2076
|
+
* @remarks Time O(log n + m), Space O(1) where m is bucket size
|
|
2077
|
+
|
|
2078
|
+
|
|
2079
|
+
|
|
2080
|
+
|
|
2081
|
+
|
|
2082
|
+
|
|
2083
|
+
|
|
2084
|
+
|
|
2085
|
+
|
|
2086
|
+
|
|
2087
|
+
|
|
2088
|
+
|
|
2089
|
+
|
|
2090
|
+
|
|
2091
|
+
|
|
2092
|
+
|
|
2093
|
+
|
|
2094
|
+
|
|
2095
|
+
|
|
2096
|
+
|
|
2097
|
+
|
|
2098
|
+
|
|
2099
|
+
|
|
2100
|
+
|
|
2101
|
+
|
|
2102
|
+
|
|
2103
|
+
* @example
|
|
2104
|
+
* // Get entries for key
|
|
2105
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
2106
|
+
* mm.add(1, 'a');
|
|
2107
|
+
* mm.add(1, 'b');
|
|
2108
|
+
* console.log([...mm.entriesOf(1)]); // [[1, 'a'], [1, 'b']];
|
|
2109
|
+
*/
|
|
2110
|
+
*entriesOf(key: K): IterableIterator<[K, V]> {
|
|
2111
|
+
const bucket = this.get(key);
|
|
2112
|
+
if (!Array.isArray(bucket)) return;
|
|
2113
|
+
for (const v of bucket) yield [key, v];
|
|
2114
|
+
}
|
|
2115
|
+
|
|
2116
|
+
/**
|
|
2117
|
+
* Iterates over all values for a specific key.
|
|
2118
|
+
* @remarks Time O(log n + m), Space O(1) where m is bucket size
|
|
2119
|
+
|
|
2120
|
+
|
|
2121
|
+
|
|
2122
|
+
|
|
2123
|
+
|
|
2124
|
+
|
|
2125
|
+
|
|
2126
|
+
|
|
2127
|
+
|
|
2128
|
+
|
|
2129
|
+
|
|
2130
|
+
|
|
2131
|
+
|
|
2132
|
+
|
|
2133
|
+
|
|
2134
|
+
|
|
2135
|
+
|
|
2136
|
+
|
|
2137
|
+
|
|
2138
|
+
|
|
2139
|
+
|
|
2140
|
+
|
|
2141
|
+
|
|
2142
|
+
|
|
2143
|
+
|
|
2144
|
+
|
|
2145
|
+
* @example
|
|
2146
|
+
* // Get flat values for key
|
|
2147
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
2148
|
+
* mm.add(1, 'a');
|
|
2149
|
+
* mm.add(1, 'b');
|
|
2150
|
+
* console.log([...mm.valuesOf(1)]); // ['a', 'b'];
|
|
2151
|
+
*/
|
|
2152
|
+
*valuesOf(key: K): IterableIterator<V> {
|
|
2153
|
+
const bucket = this.get(key);
|
|
2154
|
+
if (!Array.isArray(bucket)) return;
|
|
2155
|
+
yield* bucket;
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
/**
|
|
2159
|
+
* Iterates over all [key, value] pairs (flattened from buckets).
|
|
2160
|
+
* @remarks Time O(T), Space O(1) where T is totalSize
|
|
2161
|
+
|
|
2162
|
+
|
|
2163
|
+
|
|
2164
|
+
|
|
2165
|
+
|
|
2166
|
+
|
|
2167
|
+
|
|
2168
|
+
|
|
2169
|
+
|
|
2170
|
+
|
|
2171
|
+
|
|
2172
|
+
|
|
2173
|
+
|
|
2174
|
+
|
|
2175
|
+
|
|
2176
|
+
|
|
2177
|
+
|
|
2178
|
+
|
|
2179
|
+
|
|
2180
|
+
|
|
2181
|
+
|
|
2182
|
+
|
|
2183
|
+
|
|
2184
|
+
|
|
2185
|
+
|
|
2186
|
+
|
|
2187
|
+
* @example
|
|
2188
|
+
* // All key-value pairs flattened
|
|
2189
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
2190
|
+
* mm.add(1, 'a');
|
|
2191
|
+
* mm.add(1, 'b');
|
|
2192
|
+
* mm.add(2, 'c');
|
|
2193
|
+
* console.log([...mm.flatEntries()]); // [[1, 'a'], [1, 'b'], [2, 'c']];
|
|
2194
|
+
*/
|
|
2195
|
+
*flatEntries(): IterableIterator<[K, V]> {
|
|
2196
|
+
for (const [k, bucket] of this) {
|
|
2197
|
+
for (const v of bucket) yield [k, v];
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
// ━━━ Navigable methods (return [K, V[]] | undefined) ━━━
|
|
2202
|
+
|
|
2203
|
+
/**
|
|
2204
|
+
* Returns the entry with the smallest key.
|
|
2205
|
+
* @remarks Time O(log n), Space O(1)
|
|
2206
|
+
|
|
2207
|
+
|
|
2208
|
+
|
|
2209
|
+
|
|
2210
|
+
|
|
2211
|
+
|
|
2212
|
+
|
|
2213
|
+
|
|
2214
|
+
|
|
2215
|
+
|
|
2216
|
+
|
|
2217
|
+
|
|
2218
|
+
|
|
2219
|
+
|
|
2220
|
+
|
|
2221
|
+
|
|
2222
|
+
|
|
2223
|
+
|
|
2224
|
+
|
|
2225
|
+
|
|
2226
|
+
|
|
2227
|
+
|
|
2228
|
+
|
|
2229
|
+
|
|
2230
|
+
|
|
2231
|
+
|
|
2232
|
+
|
|
2233
|
+
|
|
2234
|
+
|
|
2235
|
+
|
|
2236
|
+
|
|
2237
|
+
|
|
2238
|
+
|
|
2239
|
+
|
|
2240
|
+
|
|
2241
|
+
|
|
2242
|
+
|
|
2243
|
+
|
|
2244
|
+
|
|
2245
|
+
|
|
2246
|
+
|
|
2247
|
+
|
|
2248
|
+
|
|
2249
|
+
|
|
2250
|
+
|
|
2251
|
+
|
|
2252
|
+
|
|
2253
|
+
|
|
2254
|
+
|
|
2255
|
+
|
|
2256
|
+
|
|
2257
|
+
|
|
2258
|
+
|
|
2259
|
+
|
|
2260
|
+
|
|
2261
|
+
|
|
2262
|
+
|
|
2263
|
+
|
|
2264
|
+
|
|
2265
|
+
|
|
2266
|
+
|
|
2267
|
+
|
|
2268
|
+
* @example
|
|
2269
|
+
* // First entry
|
|
2270
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
2271
|
+
* mm.add(3, 'c');
|
|
2272
|
+
* mm.add(1, 'a');
|
|
2273
|
+
* console.log(mm.first()?.[0]); // 1;
|
|
2274
|
+
*/
|
|
2275
|
+
first(): [K, V[]] | undefined {
|
|
2276
|
+
const k = this.#core.getLeftMost();
|
|
2277
|
+
if (k === undefined) return undefined;
|
|
2278
|
+
const b = this.get(k);
|
|
2279
|
+
return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
|
|
2280
|
+
}
|
|
2281
|
+
|
|
2282
|
+
/**
|
|
2283
|
+
* Returns the entry with the largest key.
|
|
2284
|
+
* @remarks Time O(log n), Space O(1)
|
|
2285
|
+
|
|
2286
|
+
|
|
2287
|
+
|
|
2288
|
+
|
|
2289
|
+
|
|
2290
|
+
|
|
2291
|
+
|
|
2292
|
+
|
|
2293
|
+
|
|
2294
|
+
|
|
2295
|
+
|
|
2296
|
+
|
|
2297
|
+
|
|
2298
|
+
|
|
2299
|
+
|
|
2300
|
+
|
|
2301
|
+
|
|
2302
|
+
|
|
2303
|
+
|
|
2304
|
+
|
|
2305
|
+
|
|
2306
|
+
|
|
2307
|
+
|
|
2308
|
+
|
|
2309
|
+
|
|
2310
|
+
|
|
2311
|
+
|
|
2312
|
+
|
|
2313
|
+
|
|
2314
|
+
|
|
2315
|
+
|
|
2316
|
+
|
|
2317
|
+
|
|
2318
|
+
|
|
2319
|
+
|
|
2320
|
+
|
|
2321
|
+
|
|
2322
|
+
|
|
2323
|
+
|
|
2324
|
+
|
|
2325
|
+
|
|
2326
|
+
|
|
2327
|
+
|
|
2328
|
+
|
|
2329
|
+
|
|
2330
|
+
|
|
2331
|
+
|
|
2332
|
+
|
|
2333
|
+
|
|
2334
|
+
|
|
2335
|
+
|
|
2336
|
+
|
|
2337
|
+
|
|
2338
|
+
|
|
2339
|
+
|
|
2340
|
+
|
|
2341
|
+
|
|
2342
|
+
|
|
2343
|
+
|
|
2344
|
+
|
|
2345
|
+
|
|
2346
|
+
|
|
2347
|
+
* @example
|
|
2348
|
+
* // Last entry
|
|
2349
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
2350
|
+
* mm.add(1, 'a');
|
|
2351
|
+
* mm.add(3, 'c');
|
|
2352
|
+
* console.log(mm.last()?.[0]); // 3;
|
|
2353
|
+
*/
|
|
2354
|
+
last(): [K, V[]] | undefined {
|
|
2355
|
+
const k = this.#core.getRightMost();
|
|
2356
|
+
if (k === undefined) return undefined;
|
|
2357
|
+
const b = this.get(k);
|
|
2358
|
+
return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
|
|
2359
|
+
}
|
|
2360
|
+
|
|
2361
|
+
/**
|
|
2362
|
+
* Removes and returns the entry with the smallest key.
|
|
2363
|
+
* @remarks Time O(log n), Space O(1)
|
|
2364
|
+
|
|
2365
|
+
|
|
2366
|
+
|
|
2367
|
+
|
|
2368
|
+
|
|
2369
|
+
|
|
2370
|
+
|
|
2371
|
+
|
|
2372
|
+
|
|
2373
|
+
|
|
2374
|
+
|
|
2375
|
+
|
|
2376
|
+
|
|
2377
|
+
|
|
2378
|
+
|
|
2379
|
+
|
|
2380
|
+
|
|
2381
|
+
|
|
2382
|
+
|
|
2383
|
+
|
|
2384
|
+
|
|
2385
|
+
|
|
2386
|
+
|
|
2387
|
+
|
|
2388
|
+
|
|
2389
|
+
|
|
2390
|
+
|
|
2391
|
+
* @example
|
|
2392
|
+
* // Remove and return first
|
|
2393
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
2394
|
+
* mm.add(2, 'b');
|
|
2395
|
+
* mm.add(1, 'a');
|
|
2396
|
+
* const first = mm.pollFirst();
|
|
2397
|
+
* console.log(first?.[0]); // 1;
|
|
2398
|
+
* console.log(mm.has(1)); // false;
|
|
2399
|
+
*/
|
|
2400
|
+
pollFirst(): [K, V[]] | undefined {
|
|
2401
|
+
const e = this.first();
|
|
2402
|
+
if (!e) return undefined;
|
|
2403
|
+
this.delete(e[0]);
|
|
2404
|
+
return e;
|
|
2405
|
+
}
|
|
2406
|
+
|
|
2407
|
+
/**
|
|
2408
|
+
* Removes and returns the entry with the largest key.
|
|
2409
|
+
* @remarks Time O(log n), Space O(1)
|
|
2410
|
+
|
|
2411
|
+
|
|
2412
|
+
|
|
2413
|
+
|
|
2414
|
+
|
|
2415
|
+
|
|
2416
|
+
|
|
2417
|
+
|
|
2418
|
+
|
|
2419
|
+
|
|
2420
|
+
|
|
2421
|
+
|
|
2422
|
+
|
|
2423
|
+
|
|
2424
|
+
|
|
2425
|
+
|
|
2426
|
+
|
|
2427
|
+
|
|
2428
|
+
|
|
2429
|
+
|
|
2430
|
+
|
|
2431
|
+
|
|
2432
|
+
|
|
2433
|
+
|
|
2434
|
+
|
|
2435
|
+
|
|
2436
|
+
|
|
2437
|
+
* @example
|
|
2438
|
+
* // Remove and return last
|
|
2439
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
2440
|
+
* mm.add(1, 'a');
|
|
2441
|
+
* mm.add(3, 'c');
|
|
2442
|
+
* const last = mm.pollLast();
|
|
2443
|
+
* console.log(last?.[0]); // 3;
|
|
2444
|
+
*/
|
|
2445
|
+
pollLast(): [K, V[]] | undefined {
|
|
2446
|
+
const e = this.last();
|
|
2447
|
+
if (!e) return undefined;
|
|
2448
|
+
this.delete(e[0]);
|
|
2449
|
+
return e;
|
|
2450
|
+
}
|
|
2451
|
+
|
|
2452
|
+
/**
|
|
2453
|
+
* Returns the entry with the smallest key >= given key.
|
|
2454
|
+
* @remarks Time O(log n), Space O(1)
|
|
2455
|
+
|
|
2456
|
+
|
|
2457
|
+
|
|
2458
|
+
|
|
2459
|
+
|
|
2460
|
+
|
|
2461
|
+
|
|
2462
|
+
|
|
2463
|
+
|
|
2464
|
+
|
|
2465
|
+
|
|
2466
|
+
|
|
2467
|
+
|
|
2468
|
+
|
|
2469
|
+
|
|
2470
|
+
|
|
2471
|
+
|
|
2472
|
+
|
|
2473
|
+
|
|
2474
|
+
|
|
2475
|
+
|
|
2476
|
+
|
|
2477
|
+
|
|
2478
|
+
|
|
2479
|
+
|
|
2480
|
+
|
|
2481
|
+
|
|
2482
|
+
|
|
2483
|
+
|
|
2484
|
+
|
|
2485
|
+
|
|
2486
|
+
|
|
2487
|
+
|
|
2488
|
+
|
|
2489
|
+
|
|
2490
|
+
|
|
2491
|
+
|
|
2492
|
+
|
|
2493
|
+
|
|
2494
|
+
|
|
2495
|
+
|
|
2496
|
+
|
|
2497
|
+
|
|
2498
|
+
|
|
2499
|
+
|
|
2500
|
+
|
|
2501
|
+
|
|
2502
|
+
|
|
2503
|
+
|
|
2504
|
+
|
|
2505
|
+
|
|
2506
|
+
|
|
2507
|
+
|
|
2508
|
+
|
|
2509
|
+
|
|
2510
|
+
|
|
2511
|
+
|
|
2512
|
+
|
|
2513
|
+
|
|
2514
|
+
|
|
2515
|
+
|
|
2516
|
+
|
|
2517
|
+
|
|
2518
|
+
|
|
2519
|
+
|
|
2520
|
+
|
|
2521
|
+
|
|
2522
|
+
|
|
2523
|
+
|
|
2524
|
+
|
|
2525
|
+
|
|
2526
|
+
|
|
2527
|
+
|
|
2528
|
+
|
|
2529
|
+
|
|
2530
|
+
|
|
2531
|
+
|
|
2532
|
+
|
|
2533
|
+
|
|
2534
|
+
|
|
2535
|
+
|
|
2536
|
+
|
|
2537
|
+
|
|
2538
|
+
|
|
2539
|
+
|
|
2540
|
+
|
|
2541
|
+
|
|
2542
|
+
|
|
2543
|
+
|
|
2544
|
+
|
|
2545
|
+
|
|
2546
|
+
|
|
2547
|
+
|
|
2548
|
+
|
|
2549
|
+
|
|
2550
|
+
|
|
2551
|
+
|
|
2552
|
+
|
|
2553
|
+
|
|
2554
|
+
|
|
2555
|
+
|
|
2556
|
+
|
|
2557
|
+
|
|
2558
|
+
|
|
2559
|
+
|
|
2560
|
+
|
|
2561
|
+
|
|
2562
|
+
|
|
2563
|
+
|
|
2564
|
+
|
|
2565
|
+
|
|
2566
|
+
|
|
2567
|
+
|
|
2568
|
+
|
|
2569
|
+
|
|
2570
|
+
|
|
2571
|
+
|
|
2572
|
+
|
|
2573
|
+
|
|
2574
|
+
|
|
2575
|
+
|
|
2576
|
+
|
|
2577
|
+
|
|
2578
|
+
|
|
2579
|
+
|
|
2580
|
+
|
|
2581
|
+
|
|
2582
|
+
|
|
2583
|
+
|
|
2584
|
+
|
|
2585
|
+
|
|
2586
|
+
|
|
2587
|
+
|
|
2588
|
+
|
|
2589
|
+
|
|
2590
|
+
|
|
2591
|
+
|
|
2592
|
+
|
|
2593
|
+
|
|
2594
|
+
|
|
2595
|
+
|
|
2596
|
+
|
|
2597
|
+
|
|
2598
|
+
|
|
2599
|
+
|
|
2600
|
+
|
|
2601
|
+
|
|
2602
|
+
|
|
2603
|
+
|
|
2604
|
+
|
|
2605
|
+
|
|
2606
|
+
|
|
2607
|
+
|
|
2608
|
+
|
|
2609
|
+
|
|
2610
|
+
|
|
2611
|
+
|
|
2612
|
+
|
|
2613
|
+
|
|
2614
|
+
|
|
2615
|
+
|
|
2616
|
+
* @example
|
|
2617
|
+
* // Least key ≥ target
|
|
2618
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
2619
|
+
* mm.add(10, 'a');
|
|
2620
|
+
* mm.add(20, 'b');
|
|
2621
|
+
* mm.add(30, 'c');
|
|
2622
|
+
* console.log(mm.ceiling(15)?.[0]); // 20;
|
|
2623
|
+
*/
|
|
2624
|
+
ceiling(key: K): [K, V[]] | undefined {
|
|
2625
|
+
this._validateKey(key);
|
|
2626
|
+
const k = this.#core.ceiling(key);
|
|
2627
|
+
if (k === undefined) return undefined;
|
|
2628
|
+
const b = this.get(k);
|
|
2629
|
+
return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
|
|
2630
|
+
}
|
|
2631
|
+
|
|
2632
|
+
/**
|
|
2633
|
+
* Returns the entry with the largest key <= given key.
|
|
2634
|
+
* @remarks Time O(log n), Space O(1)
|
|
2635
|
+
|
|
2636
|
+
|
|
2637
|
+
|
|
2638
|
+
|
|
2639
|
+
|
|
2640
|
+
|
|
2641
|
+
|
|
2642
|
+
|
|
2643
|
+
|
|
2644
|
+
|
|
2645
|
+
|
|
2646
|
+
|
|
2647
|
+
|
|
2648
|
+
|
|
2649
|
+
|
|
2650
|
+
|
|
2651
|
+
|
|
2652
|
+
|
|
2653
|
+
|
|
2654
|
+
|
|
2655
|
+
|
|
2656
|
+
|
|
2657
|
+
|
|
2658
|
+
|
|
2659
|
+
|
|
2660
|
+
|
|
2661
|
+
|
|
2662
|
+
|
|
2663
|
+
|
|
2664
|
+
|
|
2665
|
+
|
|
2666
|
+
|
|
2667
|
+
|
|
2668
|
+
|
|
2669
|
+
|
|
2670
|
+
|
|
2671
|
+
|
|
2672
|
+
|
|
2673
|
+
|
|
2674
|
+
|
|
2675
|
+
|
|
2676
|
+
|
|
2677
|
+
|
|
2678
|
+
|
|
2679
|
+
|
|
2680
|
+
|
|
2681
|
+
|
|
2682
|
+
|
|
2683
|
+
|
|
2684
|
+
|
|
2685
|
+
|
|
2686
|
+
|
|
2687
|
+
|
|
2688
|
+
|
|
2689
|
+
|
|
2690
|
+
|
|
2691
|
+
|
|
2692
|
+
|
|
2693
|
+
|
|
2694
|
+
|
|
2695
|
+
|
|
2696
|
+
|
|
2697
|
+
|
|
2698
|
+
|
|
2699
|
+
|
|
2700
|
+
|
|
2701
|
+
|
|
2702
|
+
|
|
2703
|
+
|
|
2704
|
+
|
|
2705
|
+
|
|
2706
|
+
|
|
2707
|
+
|
|
2708
|
+
|
|
2709
|
+
|
|
2710
|
+
|
|
2711
|
+
|
|
2712
|
+
|
|
2713
|
+
|
|
2714
|
+
|
|
2715
|
+
|
|
2716
|
+
|
|
2717
|
+
|
|
2718
|
+
|
|
2719
|
+
|
|
2720
|
+
|
|
2721
|
+
|
|
2722
|
+
|
|
2723
|
+
|
|
2724
|
+
|
|
2725
|
+
|
|
2726
|
+
|
|
2727
|
+
|
|
2728
|
+
|
|
2729
|
+
|
|
2730
|
+
|
|
2731
|
+
|
|
2732
|
+
|
|
2733
|
+
|
|
2734
|
+
|
|
2735
|
+
|
|
2736
|
+
|
|
2737
|
+
|
|
2738
|
+
|
|
2739
|
+
|
|
2740
|
+
|
|
2741
|
+
|
|
2742
|
+
|
|
2743
|
+
|
|
2744
|
+
|
|
2745
|
+
|
|
2746
|
+
|
|
2747
|
+
|
|
2748
|
+
|
|
2749
|
+
|
|
2750
|
+
|
|
2751
|
+
|
|
2752
|
+
|
|
2753
|
+
|
|
2754
|
+
|
|
2755
|
+
|
|
2756
|
+
|
|
2757
|
+
|
|
2758
|
+
|
|
2759
|
+
|
|
2760
|
+
|
|
2761
|
+
|
|
2762
|
+
|
|
2763
|
+
|
|
2764
|
+
|
|
2765
|
+
|
|
2766
|
+
|
|
2767
|
+
|
|
2768
|
+
|
|
2769
|
+
|
|
2770
|
+
|
|
2771
|
+
|
|
2772
|
+
|
|
2773
|
+
|
|
2774
|
+
|
|
2775
|
+
|
|
2776
|
+
|
|
2777
|
+
|
|
2778
|
+
|
|
2779
|
+
|
|
2780
|
+
|
|
2781
|
+
|
|
2782
|
+
|
|
2783
|
+
|
|
2784
|
+
|
|
2785
|
+
|
|
2786
|
+
|
|
2787
|
+
|
|
2788
|
+
|
|
2789
|
+
|
|
2790
|
+
|
|
2791
|
+
|
|
2792
|
+
|
|
2793
|
+
|
|
2794
|
+
|
|
2795
|
+
|
|
2796
|
+
* @example
|
|
2797
|
+
* // Greatest key ≤ target
|
|
2798
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
2799
|
+
* mm.add(10, 'a');
|
|
2800
|
+
* mm.add(20, 'b');
|
|
2801
|
+
* mm.add(30, 'c');
|
|
2802
|
+
* console.log(mm.floor(25)?.[0]); // 20;
|
|
2803
|
+
*/
|
|
2804
|
+
floor(key: K): [K, V[]] | undefined {
|
|
2805
|
+
this._validateKey(key);
|
|
2806
|
+
const k = this.#core.floor(key);
|
|
2807
|
+
if (k === undefined) return undefined;
|
|
2808
|
+
const b = this.get(k);
|
|
2809
|
+
return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
|
|
2810
|
+
}
|
|
2811
|
+
|
|
2812
|
+
/**
|
|
2813
|
+
* Returns the entry with the smallest key > given key.
|
|
2814
|
+
* @remarks Time O(log n), Space O(1)
|
|
2815
|
+
|
|
2816
|
+
|
|
2817
|
+
|
|
2818
|
+
|
|
2819
|
+
|
|
2820
|
+
|
|
2821
|
+
|
|
2822
|
+
|
|
2823
|
+
|
|
2824
|
+
|
|
2825
|
+
|
|
2826
|
+
|
|
2827
|
+
|
|
2828
|
+
|
|
2829
|
+
|
|
2830
|
+
|
|
2831
|
+
|
|
2832
|
+
|
|
2833
|
+
|
|
2834
|
+
|
|
2835
|
+
|
|
2836
|
+
|
|
2837
|
+
|
|
2838
|
+
|
|
2839
|
+
|
|
2840
|
+
|
|
2841
|
+
|
|
2842
|
+
|
|
2843
|
+
|
|
2844
|
+
|
|
2845
|
+
|
|
2846
|
+
|
|
2847
|
+
|
|
2848
|
+
|
|
2849
|
+
|
|
2850
|
+
|
|
2851
|
+
|
|
2852
|
+
|
|
2853
|
+
|
|
2854
|
+
|
|
2855
|
+
|
|
2856
|
+
|
|
2857
|
+
|
|
2858
|
+
|
|
2859
|
+
|
|
2860
|
+
|
|
2861
|
+
|
|
2862
|
+
|
|
2863
|
+
|
|
2864
|
+
|
|
2865
|
+
|
|
2866
|
+
|
|
2867
|
+
|
|
2868
|
+
|
|
2869
|
+
|
|
2870
|
+
|
|
2871
|
+
|
|
2872
|
+
|
|
2873
|
+
|
|
2874
|
+
|
|
2875
|
+
|
|
2876
|
+
|
|
2877
|
+
|
|
2878
|
+
|
|
2879
|
+
|
|
2880
|
+
|
|
2881
|
+
|
|
2882
|
+
|
|
2883
|
+
|
|
2884
|
+
|
|
2885
|
+
|
|
2886
|
+
|
|
2887
|
+
|
|
2888
|
+
|
|
2889
|
+
|
|
2890
|
+
|
|
2891
|
+
|
|
2892
|
+
|
|
2893
|
+
|
|
2894
|
+
|
|
2895
|
+
|
|
2896
|
+
|
|
2897
|
+
|
|
2898
|
+
|
|
2899
|
+
|
|
2900
|
+
|
|
2901
|
+
|
|
2902
|
+
|
|
2903
|
+
|
|
2904
|
+
|
|
2905
|
+
|
|
2906
|
+
|
|
2907
|
+
|
|
2908
|
+
|
|
2909
|
+
|
|
2910
|
+
|
|
2911
|
+
|
|
2912
|
+
|
|
2913
|
+
|
|
2914
|
+
|
|
2915
|
+
|
|
2916
|
+
|
|
2917
|
+
|
|
2918
|
+
|
|
2919
|
+
|
|
2920
|
+
|
|
2921
|
+
|
|
2922
|
+
|
|
2923
|
+
|
|
2924
|
+
|
|
2925
|
+
|
|
2926
|
+
|
|
2927
|
+
|
|
2928
|
+
|
|
2929
|
+
|
|
2930
|
+
|
|
2931
|
+
|
|
2932
|
+
|
|
2933
|
+
|
|
2934
|
+
|
|
2935
|
+
|
|
2936
|
+
|
|
2937
|
+
|
|
2938
|
+
|
|
2939
|
+
|
|
2940
|
+
|
|
2941
|
+
* @example
|
|
2942
|
+
* // Least key > target
|
|
2943
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
2944
|
+
* mm.add(10, 'a');
|
|
2945
|
+
* mm.add(20, 'b');
|
|
2946
|
+
* console.log(mm.higher(10)?.[0]); // 20;
|
|
2947
|
+
*/
|
|
2948
|
+
higher(key: K): [K, V[]] | undefined {
|
|
2949
|
+
this._validateKey(key);
|
|
2950
|
+
const k = this.#core.higher(key);
|
|
2951
|
+
if (k === undefined) return undefined;
|
|
2952
|
+
const b = this.get(k);
|
|
2953
|
+
return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
|
|
2954
|
+
}
|
|
2955
|
+
|
|
2956
|
+
/**
|
|
2957
|
+
* Returns the entry with the largest key < given key.
|
|
2958
|
+
* @remarks Time O(log n), Space O(1)
|
|
2959
|
+
|
|
2960
|
+
|
|
2961
|
+
|
|
2962
|
+
|
|
2963
|
+
|
|
2964
|
+
|
|
2965
|
+
|
|
2966
|
+
|
|
2967
|
+
|
|
2968
|
+
|
|
2969
|
+
|
|
2970
|
+
|
|
2971
|
+
|
|
2972
|
+
|
|
2973
|
+
|
|
2974
|
+
|
|
2975
|
+
|
|
2976
|
+
|
|
2977
|
+
|
|
2978
|
+
|
|
2979
|
+
|
|
2980
|
+
|
|
2981
|
+
|
|
2982
|
+
|
|
2983
|
+
|
|
2984
|
+
|
|
2985
|
+
|
|
2986
|
+
|
|
2987
|
+
|
|
2988
|
+
|
|
2989
|
+
|
|
2990
|
+
|
|
2991
|
+
|
|
2992
|
+
|
|
2993
|
+
|
|
2994
|
+
|
|
2995
|
+
|
|
2996
|
+
|
|
2997
|
+
|
|
2998
|
+
|
|
2999
|
+
|
|
3000
|
+
|
|
3001
|
+
|
|
3002
|
+
|
|
3003
|
+
|
|
3004
|
+
|
|
3005
|
+
|
|
3006
|
+
|
|
3007
|
+
|
|
3008
|
+
|
|
3009
|
+
|
|
3010
|
+
|
|
3011
|
+
|
|
3012
|
+
|
|
3013
|
+
|
|
3014
|
+
|
|
3015
|
+
|
|
3016
|
+
|
|
3017
|
+
|
|
3018
|
+
|
|
3019
|
+
|
|
3020
|
+
|
|
3021
|
+
|
|
3022
|
+
|
|
3023
|
+
|
|
3024
|
+
|
|
3025
|
+
|
|
3026
|
+
|
|
3027
|
+
|
|
3028
|
+
|
|
3029
|
+
|
|
3030
|
+
|
|
3031
|
+
|
|
3032
|
+
|
|
3033
|
+
|
|
3034
|
+
|
|
3035
|
+
|
|
3036
|
+
|
|
3037
|
+
|
|
3038
|
+
|
|
3039
|
+
|
|
3040
|
+
|
|
3041
|
+
|
|
3042
|
+
|
|
3043
|
+
|
|
3044
|
+
|
|
3045
|
+
|
|
3046
|
+
|
|
3047
|
+
|
|
3048
|
+
|
|
3049
|
+
|
|
3050
|
+
|
|
3051
|
+
|
|
3052
|
+
|
|
3053
|
+
|
|
3054
|
+
|
|
3055
|
+
|
|
3056
|
+
|
|
3057
|
+
|
|
3058
|
+
|
|
3059
|
+
|
|
3060
|
+
|
|
3061
|
+
|
|
3062
|
+
|
|
3063
|
+
|
|
3064
|
+
|
|
3065
|
+
|
|
3066
|
+
|
|
3067
|
+
|
|
3068
|
+
|
|
3069
|
+
|
|
3070
|
+
|
|
3071
|
+
|
|
3072
|
+
|
|
3073
|
+
|
|
3074
|
+
|
|
3075
|
+
|
|
3076
|
+
|
|
3077
|
+
|
|
3078
|
+
|
|
3079
|
+
|
|
3080
|
+
|
|
3081
|
+
|
|
3082
|
+
|
|
3083
|
+
|
|
3084
|
+
|
|
3085
|
+
* @example
|
|
3086
|
+
* // Greatest key < target
|
|
3087
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
3088
|
+
* mm.add(10, 'a');
|
|
3089
|
+
* mm.add(20, 'b');
|
|
3090
|
+
* console.log(mm.lower(20)?.[0]); // 10;
|
|
3091
|
+
*/
|
|
3092
|
+
lower(key: K): [K, V[]] | undefined {
|
|
3093
|
+
this._validateKey(key);
|
|
3094
|
+
const k = this.#core.lower(key);
|
|
3095
|
+
if (k === undefined) return undefined;
|
|
3096
|
+
const b = this.get(k);
|
|
3097
|
+
return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
|
|
3098
|
+
}
|
|
3099
|
+
|
|
3100
|
+
// ━━━ Tree utilities ━━━
|
|
3101
|
+
|
|
3102
|
+
/**
|
|
3103
|
+
* Prints the internal tree structure (for debugging).
|
|
3104
|
+
* @remarks Time O(n), Space O(n)
|
|
3105
|
+
|
|
3106
|
+
|
|
3107
|
+
|
|
3108
|
+
|
|
3109
|
+
|
|
3110
|
+
|
|
3111
|
+
|
|
3112
|
+
|
|
3113
|
+
|
|
3114
|
+
|
|
3115
|
+
|
|
3116
|
+
|
|
3117
|
+
|
|
3118
|
+
|
|
3119
|
+
|
|
3120
|
+
|
|
3121
|
+
|
|
3122
|
+
|
|
3123
|
+
|
|
3124
|
+
|
|
3125
|
+
|
|
3126
|
+
|
|
3127
|
+
|
|
3128
|
+
|
|
3129
|
+
|
|
3130
|
+
|
|
3131
|
+
|
|
3132
|
+
|
|
3133
|
+
|
|
3134
|
+
|
|
3135
|
+
|
|
3136
|
+
|
|
3137
|
+
|
|
3138
|
+
|
|
3139
|
+
|
|
3140
|
+
|
|
3141
|
+
|
|
3142
|
+
|
|
3143
|
+
|
|
3144
|
+
|
|
3145
|
+
|
|
3146
|
+
|
|
3147
|
+
|
|
3148
|
+
|
|
3149
|
+
|
|
3150
|
+
|
|
3151
|
+
|
|
3152
|
+
|
|
3153
|
+
|
|
3154
|
+
|
|
3155
|
+
|
|
3156
|
+
|
|
3157
|
+
|
|
3158
|
+
|
|
3159
|
+
|
|
3160
|
+
|
|
3161
|
+
|
|
3162
|
+
|
|
3163
|
+
|
|
3164
|
+
|
|
3165
|
+
|
|
3166
|
+
|
|
3167
|
+
|
|
3168
|
+
|
|
3169
|
+
|
|
3170
|
+
|
|
3171
|
+
|
|
3172
|
+
|
|
3173
|
+
|
|
3174
|
+
|
|
3175
|
+
|
|
3176
|
+
|
|
3177
|
+
|
|
3178
|
+
|
|
3179
|
+
|
|
3180
|
+
|
|
3181
|
+
|
|
3182
|
+
|
|
3183
|
+
|
|
3184
|
+
|
|
3185
|
+
|
|
3186
|
+
|
|
3187
|
+
|
|
3188
|
+
|
|
3189
|
+
|
|
3190
|
+
|
|
3191
|
+
|
|
3192
|
+
|
|
3193
|
+
|
|
3194
|
+
|
|
3195
|
+
|
|
3196
|
+
|
|
3197
|
+
|
|
3198
|
+
|
|
3199
|
+
|
|
3200
|
+
|
|
3201
|
+
|
|
3202
|
+
|
|
3203
|
+
|
|
3204
|
+
|
|
3205
|
+
|
|
3206
|
+
|
|
3207
|
+
|
|
3208
|
+
|
|
3209
|
+
|
|
3210
|
+
|
|
3211
|
+
|
|
3212
|
+
|
|
3213
|
+
|
|
3214
|
+
|
|
3215
|
+
|
|
3216
|
+
|
|
3217
|
+
|
|
3218
|
+
|
|
3219
|
+
|
|
3220
|
+
|
|
3221
|
+
|
|
3222
|
+
|
|
3223
|
+
|
|
3224
|
+
|
|
3225
|
+
|
|
3226
|
+
|
|
3227
|
+
|
|
3228
|
+
|
|
3229
|
+
|
|
3230
|
+
|
|
3231
|
+
|
|
3232
|
+
|
|
3233
|
+
|
|
3234
|
+
|
|
3235
|
+
|
|
3236
|
+
|
|
3237
|
+
|
|
3238
|
+
|
|
3239
|
+
|
|
3240
|
+
|
|
3241
|
+
|
|
3242
|
+
|
|
3243
|
+
|
|
3244
|
+
|
|
3245
|
+
|
|
3246
|
+
|
|
3247
|
+
|
|
3248
|
+
|
|
3249
|
+
|
|
3250
|
+
|
|
3251
|
+
|
|
3252
|
+
|
|
3253
|
+
|
|
3254
|
+
|
|
3255
|
+
|
|
3256
|
+
|
|
3257
|
+
|
|
3258
|
+
|
|
3259
|
+
|
|
3260
|
+
|
|
3261
|
+
|
|
3262
|
+
|
|
3263
|
+
* @example
|
|
3264
|
+
* // Display tree
|
|
3265
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
3266
|
+
* mm.add(1, 'a');
|
|
3267
|
+
* expect(() => mm.print()).not.toThrow();
|
|
3268
|
+
*/
|
|
3269
|
+
print(): void {
|
|
3270
|
+
this.#core.print();
|
|
3271
|
+
}
|
|
3272
|
+
|
|
3273
|
+
/**
|
|
3274
|
+
* Executes a callback for each entry.
|
|
3275
|
+
* @remarks Time O(n), Space O(1)
|
|
3276
|
+
|
|
3277
|
+
|
|
3278
|
+
|
|
3279
|
+
|
|
3280
|
+
|
|
3281
|
+
|
|
3282
|
+
|
|
3283
|
+
|
|
3284
|
+
|
|
3285
|
+
|
|
3286
|
+
|
|
3287
|
+
|
|
3288
|
+
|
|
3289
|
+
|
|
3290
|
+
|
|
3291
|
+
|
|
3292
|
+
|
|
3293
|
+
|
|
3294
|
+
|
|
3295
|
+
|
|
3296
|
+
|
|
3297
|
+
|
|
3298
|
+
|
|
3299
|
+
|
|
3300
|
+
|
|
3301
|
+
|
|
3302
|
+
|
|
3303
|
+
|
|
3304
|
+
|
|
3305
|
+
|
|
3306
|
+
|
|
3307
|
+
|
|
3308
|
+
|
|
3309
|
+
|
|
3310
|
+
|
|
3311
|
+
|
|
3312
|
+
|
|
3313
|
+
|
|
3314
|
+
|
|
3315
|
+
|
|
3316
|
+
|
|
3317
|
+
|
|
3318
|
+
|
|
3319
|
+
|
|
3320
|
+
|
|
3321
|
+
|
|
3322
|
+
|
|
3323
|
+
|
|
3324
|
+
|
|
3325
|
+
|
|
3326
|
+
|
|
3327
|
+
|
|
3328
|
+
|
|
3329
|
+
|
|
3330
|
+
|
|
3331
|
+
|
|
3332
|
+
|
|
3333
|
+
|
|
3334
|
+
|
|
3335
|
+
|
|
3336
|
+
|
|
3337
|
+
|
|
3338
|
+
|
|
3339
|
+
|
|
3340
|
+
|
|
3341
|
+
|
|
3342
|
+
|
|
3343
|
+
|
|
3344
|
+
|
|
3345
|
+
|
|
3346
|
+
|
|
3347
|
+
|
|
3348
|
+
|
|
3349
|
+
|
|
3350
|
+
|
|
3351
|
+
|
|
3352
|
+
|
|
3353
|
+
|
|
3354
|
+
|
|
3355
|
+
|
|
3356
|
+
|
|
3357
|
+
|
|
3358
|
+
|
|
3359
|
+
|
|
3360
|
+
|
|
3361
|
+
|
|
3362
|
+
|
|
3363
|
+
|
|
3364
|
+
|
|
3365
|
+
|
|
3366
|
+
|
|
3367
|
+
|
|
3368
|
+
|
|
3369
|
+
|
|
3370
|
+
|
|
3371
|
+
|
|
3372
|
+
|
|
3373
|
+
|
|
3374
|
+
|
|
3375
|
+
|
|
3376
|
+
|
|
3377
|
+
|
|
3378
|
+
|
|
3379
|
+
|
|
3380
|
+
|
|
3381
|
+
|
|
3382
|
+
|
|
3383
|
+
|
|
3384
|
+
|
|
3385
|
+
|
|
3386
|
+
|
|
3387
|
+
|
|
3388
|
+
|
|
3389
|
+
|
|
3390
|
+
|
|
3391
|
+
|
|
3392
|
+
|
|
3393
|
+
|
|
3394
|
+
|
|
3395
|
+
|
|
3396
|
+
|
|
3397
|
+
|
|
3398
|
+
|
|
3399
|
+
|
|
3400
|
+
|
|
3401
|
+
|
|
3402
|
+
|
|
3403
|
+
|
|
3404
|
+
|
|
3405
|
+
|
|
3406
|
+
|
|
3407
|
+
|
|
3408
|
+
|
|
3409
|
+
|
|
3410
|
+
|
|
3411
|
+
|
|
3412
|
+
|
|
3413
|
+
|
|
3414
|
+
|
|
3415
|
+
|
|
3416
|
+
|
|
3417
|
+
|
|
3418
|
+
|
|
3419
|
+
|
|
3420
|
+
|
|
3421
|
+
|
|
3422
|
+
|
|
3423
|
+
|
|
3424
|
+
|
|
3425
|
+
|
|
3426
|
+
|
|
3427
|
+
|
|
3428
|
+
|
|
3429
|
+
|
|
3430
|
+
|
|
3431
|
+
|
|
3432
|
+
|
|
3433
|
+
|
|
3434
|
+
* @example
|
|
3435
|
+
* // Iterate entries
|
|
3436
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
3437
|
+
* mm.add(1, 'a');
|
|
3438
|
+
* mm.add(2, 'b');
|
|
3439
|
+
* const keys: number[] = [];
|
|
3440
|
+
* mm.forEach((v, k) => keys.push(k));
|
|
3441
|
+
* console.log(keys); // [1, 2];
|
|
3442
|
+
*/
|
|
3443
|
+
forEach(callback: (value: V[], key: K, map: this) => void): void {
|
|
3444
|
+
for (const [k, v] of this) {
|
|
3445
|
+
callback(v, k, this);
|
|
3446
|
+
}
|
|
3447
|
+
}
|
|
3448
|
+
|
|
705
3449
|
/**
|
|
706
|
-
*
|
|
707
|
-
* @remarks Time O(n), Space O(
|
|
3450
|
+
* Creates a new map with entries that pass the predicate.
|
|
3451
|
+
* @remarks Time O(n), Space O(n)
|
|
3452
|
+
|
|
3453
|
+
|
|
3454
|
+
|
|
3455
|
+
|
|
3456
|
+
|
|
3457
|
+
|
|
3458
|
+
|
|
3459
|
+
|
|
3460
|
+
|
|
3461
|
+
|
|
3462
|
+
|
|
3463
|
+
|
|
3464
|
+
|
|
3465
|
+
|
|
3466
|
+
|
|
3467
|
+
|
|
3468
|
+
|
|
3469
|
+
|
|
3470
|
+
|
|
3471
|
+
|
|
3472
|
+
|
|
3473
|
+
|
|
3474
|
+
|
|
3475
|
+
|
|
3476
|
+
|
|
3477
|
+
|
|
3478
|
+
|
|
3479
|
+
|
|
3480
|
+
|
|
3481
|
+
|
|
3482
|
+
|
|
3483
|
+
|
|
3484
|
+
|
|
3485
|
+
|
|
3486
|
+
|
|
3487
|
+
|
|
3488
|
+
|
|
3489
|
+
|
|
3490
|
+
|
|
3491
|
+
|
|
3492
|
+
|
|
3493
|
+
|
|
3494
|
+
|
|
3495
|
+
|
|
3496
|
+
|
|
3497
|
+
|
|
3498
|
+
|
|
3499
|
+
|
|
3500
|
+
|
|
3501
|
+
|
|
3502
|
+
|
|
3503
|
+
|
|
3504
|
+
|
|
3505
|
+
|
|
3506
|
+
|
|
3507
|
+
|
|
3508
|
+
|
|
3509
|
+
|
|
3510
|
+
|
|
3511
|
+
|
|
3512
|
+
|
|
3513
|
+
|
|
3514
|
+
|
|
3515
|
+
|
|
3516
|
+
|
|
3517
|
+
|
|
3518
|
+
|
|
3519
|
+
|
|
3520
|
+
|
|
3521
|
+
|
|
3522
|
+
|
|
3523
|
+
|
|
3524
|
+
|
|
3525
|
+
|
|
3526
|
+
|
|
3527
|
+
|
|
3528
|
+
|
|
3529
|
+
|
|
3530
|
+
|
|
3531
|
+
|
|
3532
|
+
|
|
3533
|
+
|
|
3534
|
+
|
|
3535
|
+
|
|
3536
|
+
|
|
3537
|
+
|
|
3538
|
+
|
|
3539
|
+
|
|
3540
|
+
|
|
3541
|
+
|
|
3542
|
+
|
|
3543
|
+
|
|
3544
|
+
|
|
3545
|
+
|
|
3546
|
+
|
|
3547
|
+
|
|
3548
|
+
|
|
3549
|
+
|
|
3550
|
+
|
|
3551
|
+
|
|
3552
|
+
|
|
3553
|
+
|
|
3554
|
+
|
|
3555
|
+
|
|
3556
|
+
|
|
3557
|
+
|
|
3558
|
+
|
|
3559
|
+
|
|
3560
|
+
|
|
3561
|
+
|
|
3562
|
+
|
|
3563
|
+
|
|
3564
|
+
|
|
3565
|
+
|
|
3566
|
+
|
|
3567
|
+
|
|
3568
|
+
|
|
3569
|
+
|
|
3570
|
+
|
|
3571
|
+
|
|
3572
|
+
|
|
3573
|
+
|
|
3574
|
+
|
|
3575
|
+
|
|
3576
|
+
|
|
3577
|
+
|
|
3578
|
+
|
|
3579
|
+
|
|
3580
|
+
|
|
3581
|
+
|
|
3582
|
+
|
|
3583
|
+
|
|
3584
|
+
|
|
3585
|
+
|
|
3586
|
+
|
|
3587
|
+
|
|
3588
|
+
|
|
3589
|
+
|
|
3590
|
+
|
|
3591
|
+
|
|
3592
|
+
|
|
3593
|
+
|
|
3594
|
+
|
|
3595
|
+
|
|
3596
|
+
|
|
3597
|
+
|
|
3598
|
+
|
|
3599
|
+
|
|
3600
|
+
|
|
3601
|
+
|
|
3602
|
+
|
|
3603
|
+
|
|
3604
|
+
|
|
3605
|
+
|
|
3606
|
+
|
|
3607
|
+
|
|
3608
|
+
|
|
3609
|
+
|
|
3610
|
+
* @example
|
|
3611
|
+
* // Filter entries
|
|
3612
|
+
* const mm = new TreeMultiMap<number, string>();
|
|
3613
|
+
* mm.add(1, 'a');
|
|
3614
|
+
* mm.add(2, 'b');
|
|
3615
|
+
* mm.add(3, 'c');
|
|
3616
|
+
* const filtered = mm.filter((v, k) => k > 1);
|
|
3617
|
+
* console.log([...filtered.keys()]); // [2, 3];
|
|
708
3618
|
*/
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
3619
|
+
filter(predicate: (value: V[], key: K, map: this) => boolean): TreeMultiMap<K, V, R> {
|
|
3620
|
+
const filtered: [K, V[]][] = [];
|
|
3621
|
+
for (const [k, v] of this) {
|
|
3622
|
+
if (predicate(v, k, this)) filtered.push([k, v]);
|
|
713
3623
|
}
|
|
3624
|
+
return new TreeMultiMap<K, V, R>(filtered, { comparator: this.comparator });
|
|
714
3625
|
}
|
|
715
3626
|
|
|
716
3627
|
/**
|
|
717
|
-
*
|
|
718
|
-
* @remarks Time O(n), Space O(
|
|
3628
|
+
* Creates a new map by transforming each entry.
|
|
3629
|
+
* @remarks Time O(n log n), Space O(n)
|
|
3630
|
+
|
|
3631
|
+
|
|
3632
|
+
|
|
3633
|
+
|
|
3634
|
+
|
|
3635
|
+
|
|
3636
|
+
|
|
3637
|
+
|
|
3638
|
+
|
|
3639
|
+
|
|
3640
|
+
|
|
3641
|
+
|
|
3642
|
+
|
|
3643
|
+
|
|
3644
|
+
|
|
3645
|
+
|
|
3646
|
+
|
|
3647
|
+
|
|
3648
|
+
|
|
3649
|
+
|
|
3650
|
+
|
|
3651
|
+
|
|
3652
|
+
|
|
3653
|
+
|
|
3654
|
+
|
|
3655
|
+
|
|
3656
|
+
|
|
3657
|
+
|
|
3658
|
+
|
|
3659
|
+
|
|
3660
|
+
|
|
3661
|
+
|
|
3662
|
+
|
|
3663
|
+
|
|
3664
|
+
|
|
3665
|
+
|
|
3666
|
+
|
|
3667
|
+
|
|
3668
|
+
|
|
3669
|
+
|
|
3670
|
+
|
|
3671
|
+
|
|
3672
|
+
|
|
3673
|
+
|
|
3674
|
+
|
|
3675
|
+
|
|
3676
|
+
|
|
3677
|
+
|
|
3678
|
+
|
|
3679
|
+
|
|
3680
|
+
|
|
3681
|
+
|
|
3682
|
+
|
|
3683
|
+
|
|
3684
|
+
|
|
3685
|
+
|
|
3686
|
+
|
|
3687
|
+
|
|
3688
|
+
|
|
3689
|
+
|
|
3690
|
+
|
|
3691
|
+
|
|
3692
|
+
|
|
719
3693
|
|
|
720
3694
|
|
|
721
3695
|
|
|
@@ -759,20 +3733,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
759
3733
|
|
|
760
3734
|
|
|
761
3735
|
|
|
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];
|
|
768
|
-
*/
|
|
769
|
-
*keys(): IterableIterator<K> {
|
|
770
|
-
yield* this.#core.keys();
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
/**
|
|
774
|
-
* Iterates over all buckets.
|
|
775
|
-
* @remarks Time O(n), Space O(1)
|
|
776
3736
|
|
|
777
3737
|
|
|
778
3738
|
|
|
@@ -816,83 +3776,112 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
816
3776
|
|
|
817
3777
|
|
|
818
3778
|
|
|
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']];
|
|
825
|
-
*/
|
|
826
|
-
*values(): IterableIterator<V[]> {
|
|
827
|
-
for (const [, bucket] of this) yield bucket;
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
// ---- entry-flat views ----
|
|
831
|
-
|
|
832
|
-
/**
|
|
833
|
-
* Iterates over all entries for a specific key.
|
|
834
|
-
* @remarks Time O(log n + m), Space O(1) where m is bucket size
|
|
835
3779
|
|
|
836
3780
|
|
|
837
3781
|
|
|
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']];
|
|
844
|
-
*/
|
|
845
|
-
*entriesOf(key: K): IterableIterator<[K, V]> {
|
|
846
|
-
const bucket = this.get(key);
|
|
847
|
-
if (!Array.isArray(bucket)) return;
|
|
848
|
-
for (const v of bucket) yield [key, v];
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
/**
|
|
852
|
-
* Iterates over all values for a specific key.
|
|
853
|
-
* @remarks Time O(log n + m), Space O(1) where m is bucket size
|
|
854
3782
|
|
|
855
3783
|
|
|
856
3784
|
|
|
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'];
|
|
863
|
-
*/
|
|
864
|
-
*valuesOf(key: K): IterableIterator<V> {
|
|
865
|
-
const bucket = this.get(key);
|
|
866
|
-
if (!Array.isArray(bucket)) return;
|
|
867
|
-
yield* bucket;
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
/**
|
|
871
|
-
* Iterates over all [key, value] pairs (flattened from buckets).
|
|
872
|
-
* @remarks Time O(T), Space O(1) where T is totalSize
|
|
873
3785
|
|
|
874
3786
|
|
|
875
3787
|
|
|
876
3788
|
* @example
|
|
877
|
-
* //
|
|
3789
|
+
* // Transform values
|
|
878
3790
|
* const mm = new TreeMultiMap<number, string>();
|
|
879
3791
|
* mm.add(1, 'a');
|
|
880
|
-
* mm.
|
|
881
|
-
*
|
|
882
|
-
* console.log([...mm.flatEntries()]); // [[1, 'a'], [1, 'b'], [2, 'c']];
|
|
3792
|
+
* const mapped = mm.map((v, k) => [k, v.map(s => s.toUpperCase())] as [number, string[]]);
|
|
3793
|
+
* console.log(mapped.get(1)); // ['A'];
|
|
883
3794
|
*/
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
3795
|
+
map<V2>(
|
|
3796
|
+
mapper: (value: V[], key: K, map: this) => [K, V2[]]
|
|
3797
|
+
): TreeMultiMap<K, V2, R> {
|
|
3798
|
+
const mapped: [K, V2[]][] = [];
|
|
3799
|
+
for (const [k, v] of this) {
|
|
3800
|
+
mapped.push(mapper(v, k, this));
|
|
887
3801
|
}
|
|
3802
|
+
return new TreeMultiMap<K, V2, R>(mapped, { comparator: this.comparator });
|
|
888
3803
|
}
|
|
889
3804
|
|
|
890
|
-
// ━━━ Navigable methods (return [K, V[]] | undefined) ━━━
|
|
891
|
-
|
|
892
3805
|
/**
|
|
893
|
-
*
|
|
894
|
-
* @remarks Time O(
|
|
895
|
-
|
|
3806
|
+
* Reduces all entries to a single value.
|
|
3807
|
+
* @remarks Time O(n), Space O(1)
|
|
3808
|
+
|
|
3809
|
+
|
|
3810
|
+
|
|
3811
|
+
|
|
3812
|
+
|
|
3813
|
+
|
|
3814
|
+
|
|
3815
|
+
|
|
3816
|
+
|
|
3817
|
+
|
|
3818
|
+
|
|
3819
|
+
|
|
3820
|
+
|
|
3821
|
+
|
|
3822
|
+
|
|
3823
|
+
|
|
3824
|
+
|
|
3825
|
+
|
|
3826
|
+
|
|
3827
|
+
|
|
3828
|
+
|
|
3829
|
+
|
|
3830
|
+
|
|
3831
|
+
|
|
3832
|
+
|
|
3833
|
+
|
|
3834
|
+
|
|
3835
|
+
|
|
3836
|
+
|
|
3837
|
+
|
|
3838
|
+
|
|
3839
|
+
|
|
3840
|
+
|
|
3841
|
+
|
|
3842
|
+
|
|
3843
|
+
|
|
3844
|
+
|
|
3845
|
+
|
|
3846
|
+
|
|
3847
|
+
|
|
3848
|
+
|
|
3849
|
+
|
|
3850
|
+
|
|
3851
|
+
|
|
3852
|
+
|
|
3853
|
+
|
|
3854
|
+
|
|
3855
|
+
|
|
3856
|
+
|
|
3857
|
+
|
|
3858
|
+
|
|
3859
|
+
|
|
3860
|
+
|
|
3861
|
+
|
|
3862
|
+
|
|
3863
|
+
|
|
3864
|
+
|
|
3865
|
+
|
|
3866
|
+
|
|
3867
|
+
|
|
3868
|
+
|
|
3869
|
+
|
|
3870
|
+
|
|
3871
|
+
|
|
3872
|
+
|
|
3873
|
+
|
|
3874
|
+
|
|
3875
|
+
|
|
3876
|
+
|
|
3877
|
+
|
|
3878
|
+
|
|
3879
|
+
|
|
3880
|
+
|
|
3881
|
+
|
|
3882
|
+
|
|
3883
|
+
|
|
3884
|
+
|
|
896
3885
|
|
|
897
3886
|
|
|
898
3887
|
|
|
@@ -908,24 +3897,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
908
3897
|
|
|
909
3898
|
|
|
910
3899
|
|
|
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;
|
|
917
|
-
*/
|
|
918
|
-
first(): [K, V[]] | undefined {
|
|
919
|
-
const k = this.#core.getLeftMost();
|
|
920
|
-
if (k === undefined) return undefined;
|
|
921
|
-
const b = this.get(k);
|
|
922
|
-
return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
|
|
923
|
-
}
|
|
924
|
-
|
|
925
|
-
/**
|
|
926
|
-
* Returns the entry with the largest key.
|
|
927
|
-
* @remarks Time O(log n), Space O(1)
|
|
928
|
-
|
|
929
3900
|
|
|
930
3901
|
|
|
931
3902
|
|
|
@@ -941,69 +3912,12 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
941
3912
|
|
|
942
3913
|
|
|
943
3914
|
|
|
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;
|
|
950
|
-
*/
|
|
951
|
-
last(): [K, V[]] | undefined {
|
|
952
|
-
const k = this.#core.getRightMost();
|
|
953
|
-
if (k === undefined) return undefined;
|
|
954
|
-
const b = this.get(k);
|
|
955
|
-
return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
/**
|
|
959
|
-
* Removes and returns the entry with the smallest key.
|
|
960
|
-
* @remarks Time O(log n), Space O(1)
|
|
961
|
-
|
|
962
3915
|
|
|
963
3916
|
|
|
964
3917
|
|
|
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;
|
|
973
|
-
*/
|
|
974
|
-
pollFirst(): [K, V[]] | undefined {
|
|
975
|
-
const e = this.first();
|
|
976
|
-
if (!e) return undefined;
|
|
977
|
-
this.delete(e[0]);
|
|
978
|
-
return e;
|
|
979
|
-
}
|
|
980
|
-
|
|
981
|
-
/**
|
|
982
|
-
* Removes and returns the entry with the largest key.
|
|
983
|
-
* @remarks Time O(log n), Space O(1)
|
|
984
|
-
|
|
985
3918
|
|
|
986
3919
|
|
|
987
3920
|
|
|
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;
|
|
995
|
-
*/
|
|
996
|
-
pollLast(): [K, V[]] | undefined {
|
|
997
|
-
const e = this.last();
|
|
998
|
-
if (!e) return undefined;
|
|
999
|
-
this.delete(e[0]);
|
|
1000
|
-
return e;
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
/**
|
|
1004
|
-
* Returns the entry with the smallest key >= given key.
|
|
1005
|
-
* @remarks Time O(log n), Space O(1)
|
|
1006
|
-
|
|
1007
3921
|
|
|
1008
3922
|
|
|
1009
3923
|
|
|
@@ -1050,29 +3964,24 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
1050
3964
|
|
|
1051
3965
|
|
|
1052
3966
|
* @example
|
|
1053
|
-
* //
|
|
1054
|
-
* const mm = new TreeMultiMap<number,
|
|
1055
|
-
* mm.add(
|
|
1056
|
-
* mm.add(
|
|
1057
|
-
* mm.
|
|
1058
|
-
* console.log(
|
|
3967
|
+
* // Aggregate
|
|
3968
|
+
* const mm = new TreeMultiMap<number, number>();
|
|
3969
|
+
* mm.add(1, 10);
|
|
3970
|
+
* mm.add(2, 20);
|
|
3971
|
+
* const sum = mm.reduce((acc, v) => acc + v.reduce((a, b) => a + b, 0), 0);
|
|
3972
|
+
* console.log(sum); // 30;
|
|
1059
3973
|
*/
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
const k
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
return
|
|
3974
|
+
reduce<U>(callback: (accumulator: U, value: V[], key: K, map: this) => U, initialValue: U): U {
|
|
3975
|
+
let acc = initialValue;
|
|
3976
|
+
for (const [k, v] of this) {
|
|
3977
|
+
acc = callback(acc, v, k, this);
|
|
3978
|
+
}
|
|
3979
|
+
return acc;
|
|
1066
3980
|
}
|
|
1067
3981
|
|
|
1068
3982
|
/**
|
|
1069
|
-
*
|
|
1070
|
-
* @remarks Time O(log n), Space O(
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
3983
|
+
* Sets multiple entries at once.
|
|
3984
|
+
* @remarks Time O(m log n), Space O(m) where m is input size
|
|
1076
3985
|
|
|
1077
3986
|
|
|
1078
3987
|
|
|
@@ -1114,26 +4023,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
1114
4023
|
|
|
1115
4024
|
|
|
1116
4025
|
|
|
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;
|
|
1124
|
-
*/
|
|
1125
|
-
floor(key: K): [K, V[]] | undefined {
|
|
1126
|
-
this._validateKey(key);
|
|
1127
|
-
const k = this.#core.floor(key);
|
|
1128
|
-
if (k === undefined) return undefined;
|
|
1129
|
-
const b = this.get(k);
|
|
1130
|
-
return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
|
-
/**
|
|
1134
|
-
* Returns the entry with the smallest key > given key.
|
|
1135
|
-
* @remarks Time O(log n), Space O(1)
|
|
1136
|
-
|
|
1137
4026
|
|
|
1138
4027
|
|
|
1139
4028
|
|
|
@@ -1167,25 +4056,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
1167
4056
|
|
|
1168
4057
|
|
|
1169
4058
|
|
|
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;
|
|
1176
|
-
*/
|
|
1177
|
-
higher(key: K): [K, V[]] | undefined {
|
|
1178
|
-
this._validateKey(key);
|
|
1179
|
-
const k = this.#core.higher(key);
|
|
1180
|
-
if (k === undefined) return undefined;
|
|
1181
|
-
const b = this.get(k);
|
|
1182
|
-
return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
|
|
1183
|
-
}
|
|
1184
|
-
|
|
1185
|
-
/**
|
|
1186
|
-
* Returns the entry with the largest key < given key.
|
|
1187
|
-
* @remarks Time O(log n), Space O(1)
|
|
1188
|
-
|
|
1189
4059
|
|
|
1190
4060
|
|
|
1191
4061
|
|
|
@@ -1219,26 +4089,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
1219
4089
|
|
|
1220
4090
|
|
|
1221
4091
|
|
|
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;
|
|
1228
|
-
*/
|
|
1229
|
-
lower(key: K): [K, V[]] | undefined {
|
|
1230
|
-
this._validateKey(key);
|
|
1231
|
-
const k = this.#core.lower(key);
|
|
1232
|
-
if (k === undefined) return undefined;
|
|
1233
|
-
const b = this.get(k);
|
|
1234
|
-
return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
// ━━━ Tree utilities ━━━
|
|
1238
|
-
|
|
1239
|
-
/**
|
|
1240
|
-
* Prints the internal tree structure (for debugging).
|
|
1241
|
-
* @remarks Time O(n), Space O(n)
|
|
1242
4092
|
|
|
1243
4093
|
|
|
1244
4094
|
|
|
@@ -1283,21 +4133,23 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
1283
4133
|
|
|
1284
4134
|
|
|
1285
4135
|
* @example
|
|
1286
|
-
* //
|
|
4136
|
+
* // Set multiple entries
|
|
1287
4137
|
* const mm = new TreeMultiMap<number, string>();
|
|
1288
|
-
* mm.
|
|
1289
|
-
*
|
|
4138
|
+
* mm.setMany([[1, ['a']], [2, ['b']]]);
|
|
4139
|
+
* console.log(mm.size); // 2;
|
|
1290
4140
|
*/
|
|
1291
|
-
|
|
1292
|
-
|
|
4141
|
+
setMany(keysNodesEntriesOrRaws: Iterable<K | [K | null | undefined, V[] | undefined]>): boolean[] {
|
|
4142
|
+
const results: boolean[] = [];
|
|
4143
|
+
for (const x of keysNodesEntriesOrRaws) {
|
|
4144
|
+
// Call implementation directly: entry can be K or [K, V[]] or [K, undefined]
|
|
4145
|
+
results.push(this.set(x));
|
|
4146
|
+
}
|
|
4147
|
+
return results;
|
|
1293
4148
|
}
|
|
1294
4149
|
|
|
1295
4150
|
/**
|
|
1296
|
-
*
|
|
1297
|
-
* @remarks Time O(n), Space O(
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
4151
|
+
* Searches for entries within a key range.
|
|
4152
|
+
* @remarks Time O(log n + k), Space O(k) where k is result size
|
|
1301
4153
|
|
|
1302
4154
|
|
|
1303
4155
|
|
|
@@ -1338,24 +4190,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
1338
4190
|
|
|
1339
4191
|
|
|
1340
4192
|
|
|
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];
|
|
1349
|
-
*/
|
|
1350
|
-
forEach(callback: (value: V[], key: K, map: this) => void): void {
|
|
1351
|
-
for (const [k, v] of this) {
|
|
1352
|
-
callback(v, k, this);
|
|
1353
|
-
}
|
|
1354
|
-
}
|
|
1355
|
-
|
|
1356
|
-
/**
|
|
1357
|
-
* Creates a new map with entries that pass the predicate.
|
|
1358
|
-
* @remarks Time O(n), Space O(n)
|
|
1359
4193
|
|
|
1360
4194
|
|
|
1361
4195
|
|
|
@@ -1399,26 +4233,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
1399
4233
|
|
|
1400
4234
|
|
|
1401
4235
|
|
|
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];
|
|
1410
|
-
*/
|
|
1411
|
-
filter(predicate: (value: V[], key: K, map: this) => boolean): TreeMultiMap<K, V, R> {
|
|
1412
|
-
const filtered: [K, V[]][] = [];
|
|
1413
|
-
for (const [k, v] of this) {
|
|
1414
|
-
if (predicate(v, k, this)) filtered.push([k, v]);
|
|
1415
|
-
}
|
|
1416
|
-
return new TreeMultiMap<K, V, R>(filtered, { comparator: this.comparator });
|
|
1417
|
-
}
|
|
1418
|
-
|
|
1419
|
-
/**
|
|
1420
|
-
* Creates a new map by transforming each entry.
|
|
1421
|
-
* @remarks Time O(n log n), Space O(n)
|
|
1422
4236
|
|
|
1423
4237
|
|
|
1424
4238
|
|
|
@@ -1463,25 +4277,28 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
1463
4277
|
|
|
1464
4278
|
|
|
1465
4279
|
* @example
|
|
1466
|
-
* //
|
|
4280
|
+
* // Find keys in range
|
|
1467
4281
|
* const mm = new TreeMultiMap<number, string>();
|
|
1468
|
-
* mm.add(
|
|
1469
|
-
*
|
|
1470
|
-
*
|
|
4282
|
+
* mm.add(10, 'a');
|
|
4283
|
+
* mm.add(20, 'b');
|
|
4284
|
+
* mm.add(30, 'c');
|
|
4285
|
+
* const result = mm.rangeSearch([15, 25]);
|
|
4286
|
+
* console.log(result.length); // 1;
|
|
1471
4287
|
*/
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
mapped.push(mapper(v, k, this));
|
|
1478
|
-
}
|
|
1479
|
-
return new TreeMultiMap<K, V2, R>(mapped, { comparator: this.comparator });
|
|
4288
|
+
rangeSearch<C extends (node: RedBlackTreeNode<K, V[]>) => unknown>(
|
|
4289
|
+
range: Range<K> | [K, K],
|
|
4290
|
+
callback?: C
|
|
4291
|
+
): ReturnType<C>[] {
|
|
4292
|
+
return this.#core.rangeSearch(range, callback as (node: RedBlackTreeNode<K, V[]>) => ReturnType<C>);
|
|
1480
4293
|
}
|
|
1481
4294
|
|
|
1482
4295
|
/**
|
|
1483
|
-
*
|
|
1484
|
-
* @remarks Time O(n), Space O(
|
|
4296
|
+
* Creates a shallow clone of this map.
|
|
4297
|
+
* @remarks Time O(n log n), Space O(n)
|
|
4298
|
+
|
|
4299
|
+
|
|
4300
|
+
|
|
4301
|
+
|
|
1485
4302
|
|
|
1486
4303
|
|
|
1487
4304
|
|
|
@@ -1525,25 +4342,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
1525
4342
|
|
|
1526
4343
|
|
|
1527
4344
|
|
|
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;
|
|
1535
|
-
*/
|
|
1536
|
-
reduce<U>(callback: (accumulator: U, value: V[], key: K, map: this) => U, initialValue: U): U {
|
|
1537
|
-
let acc = initialValue;
|
|
1538
|
-
for (const [k, v] of this) {
|
|
1539
|
-
acc = callback(acc, v, k, this);
|
|
1540
|
-
}
|
|
1541
|
-
return acc;
|
|
1542
|
-
}
|
|
1543
|
-
|
|
1544
|
-
/**
|
|
1545
|
-
* Sets multiple entries at once.
|
|
1546
|
-
* @remarks Time O(m log n), Space O(m) where m is input size
|
|
1547
4345
|
|
|
1548
4346
|
|
|
1549
4347
|
|
|
@@ -1579,24 +4377,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
1579
4377
|
|
|
1580
4378
|
|
|
1581
4379
|
|
|
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;
|
|
1587
|
-
*/
|
|
1588
|
-
setMany(keysNodesEntriesOrRaws: Iterable<K | [K | null | undefined, V[] | undefined]>): boolean[] {
|
|
1589
|
-
const results: boolean[] = [];
|
|
1590
|
-
for (const x of keysNodesEntriesOrRaws) {
|
|
1591
|
-
// Call implementation directly: entry can be K or [K, V[]] or [K, undefined]
|
|
1592
|
-
results.push(this.set(x));
|
|
1593
|
-
}
|
|
1594
|
-
return results;
|
|
1595
|
-
}
|
|
1596
|
-
|
|
1597
|
-
/**
|
|
1598
|
-
* Searches for entries within a key range.
|
|
1599
|
-
* @remarks Time O(log n + k), Space O(k) where k is result size
|
|
1600
4380
|
|
|
1601
4381
|
|
|
1602
4382
|
|
|
@@ -1631,25 +4411,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
1631
4411
|
|
|
1632
4412
|
|
|
1633
4413
|
|
|
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;
|
|
1642
|
-
*/
|
|
1643
|
-
rangeSearch<C extends (node: RedBlackTreeNode<K, V[]>) => unknown>(
|
|
1644
|
-
range: Range<K> | [K, K],
|
|
1645
|
-
callback?: C
|
|
1646
|
-
): ReturnType<C>[] {
|
|
1647
|
-
return this.#core.rangeSearch(range, callback as (node: RedBlackTreeNode<K, V[]>) => ReturnType<C>);
|
|
1648
|
-
}
|
|
1649
|
-
|
|
1650
|
-
/**
|
|
1651
|
-
* Creates a shallow clone of this map.
|
|
1652
|
-
* @remarks Time O(n log n), Space O(n)
|
|
1653
4414
|
|
|
1654
4415
|
|
|
1655
4416
|
|
|
@@ -1690,6 +4451,66 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
|
|
|
1690
4451
|
|
|
1691
4452
|
|
|
1692
4453
|
|
|
4454
|
+
* @example
|
|
4455
|
+
* // Order-statistic on BST
|
|
4456
|
+
* const tree = new TreeMultiMap<number>([30, 10, 50, 20, 40], { enableOrderStatistic: true });
|
|
4457
|
+
* console.log(tree.getByRank(0)); // 10;
|
|
4458
|
+
* console.log(tree.getByRank(4)); // 50;
|
|
4459
|
+
* console.log(tree.getRank(30)); // 2;
|
|
4460
|
+
*/
|
|
4461
|
+
// ─── Order-Statistic Methods ───────────────────────────
|
|
4462
|
+
|
|
4463
|
+
getByRank(k: number): [K, V[]] | undefined {
|
|
4464
|
+
const key = this.#core.getByRank(k);
|
|
4465
|
+
if (key === undefined) return undefined;
|
|
4466
|
+
return [key, this.#core.get(key) ?? []];
|
|
4467
|
+
}
|
|
4468
|
+
|
|
4469
|
+
/**
|
|
4470
|
+
* Get the rank of a key in sorted order
|
|
4471
|
+
* @example
|
|
4472
|
+
* // Get the rank of a key in sorted order
|
|
4473
|
+
* const tree = new TreeMultiMap<number>(
|
|
4474
|
+
* [10, 20, 30, 40, 50],
|
|
4475
|
+
* { enableOrderStatistic: true }
|
|
4476
|
+
* );
|
|
4477
|
+
* console.log(tree.getRank(10)); // 0; // smallest → rank 0
|
|
4478
|
+
* console.log(tree.getRank(30)); // 2; // 2 elements before 30 in tree order
|
|
4479
|
+
* console.log(tree.getRank(50)); // 4; // largest → rank 4
|
|
4480
|
+
* console.log(tree.getRank(25)); // 2;
|
|
4481
|
+
*/
|
|
4482
|
+
getRank(key: K): number {
|
|
4483
|
+
return this.#core.getRank(key);
|
|
4484
|
+
}
|
|
4485
|
+
|
|
4486
|
+
/**
|
|
4487
|
+
* Get elements by rank range
|
|
4488
|
+
|
|
4489
|
+
* @example
|
|
4490
|
+
* // Pagination with rangeByRank
|
|
4491
|
+
* const tree = new TreeMultiMap<number>(
|
|
4492
|
+
* [10, 20, 30, 40, 50, 60, 70, 80, 90],
|
|
4493
|
+
* { enableOrderStatistic: true }
|
|
4494
|
+
* );
|
|
4495
|
+
* const pageSize = 3;
|
|
4496
|
+
*
|
|
4497
|
+
* // Page 1
|
|
4498
|
+
* console.log(tree.rangeByRank(0, pageSize - 1)); // [10, 20, 30];
|
|
4499
|
+
* // Page 2
|
|
4500
|
+
* console.log(tree.rangeByRank(pageSize, 2 * pageSize - 1)); // [40, 50, 60];
|
|
4501
|
+
* // Page 3
|
|
4502
|
+
* console.log(tree.rangeByRank(2 * pageSize, 3 * pageSize - 1)); // [70, 80, 90];
|
|
4503
|
+
*/
|
|
4504
|
+
rangeByRank(start: number, end: number): Array<[K, V[]]> {
|
|
4505
|
+
const keys = this.#core.rangeByRank(start, end);
|
|
4506
|
+
return keys
|
|
4507
|
+
.filter((k): k is K => k !== undefined)
|
|
4508
|
+
.map(k => [k, this.#core.get(k) ?? []] as [K, V[]]);
|
|
4509
|
+
}
|
|
4510
|
+
|
|
4511
|
+
/**
|
|
4512
|
+
* Deep copy
|
|
4513
|
+
|
|
1693
4514
|
|
|
1694
4515
|
|
|
1695
4516
|
|