data-structure-typed 2.0.4 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -1
- package/COMMANDS.md +17 -0
- package/README.md +11 -11
- package/benchmark/report.html +13 -77
- package/benchmark/report.json +158 -190
- package/dist/cjs/data-structures/base/iterable-element-base.d.ts +186 -83
- package/dist/cjs/data-structures/base/iterable-element-base.js +149 -107
- package/dist/cjs/data-structures/base/iterable-element-base.js.map +1 -1
- package/dist/cjs/data-structures/base/iterable-entry-base.d.ts +95 -119
- package/dist/cjs/data-structures/base/iterable-entry-base.js +59 -116
- package/dist/cjs/data-structures/base/iterable-entry-base.js.map +1 -1
- package/dist/cjs/data-structures/base/linear-base.d.ts +250 -192
- package/dist/cjs/data-structures/base/linear-base.js +137 -274
- package/dist/cjs/data-structures/base/linear-base.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
- package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js +171 -205
- package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +135 -87
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/avl-tree.d.ts +138 -149
- package/dist/cjs/data-structures/binary-tree/avl-tree.js +208 -195
- package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +476 -632
- package/dist/cjs/data-structures/binary-tree/binary-tree.js +608 -875
- package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/bst.d.ts +258 -306
- package/dist/cjs/data-structures/binary-tree/bst.js +505 -481
- package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/red-black-tree.d.ts +107 -179
- package/dist/cjs/data-structures/binary-tree/red-black-tree.js +114 -209
- package/dist/cjs/data-structures/binary-tree/red-black-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/tree-counter.d.ts +132 -154
- package/dist/cjs/data-structures/binary-tree/tree-counter.js +172 -203
- package/dist/cjs/data-structures/binary-tree/tree-counter.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +105 -85
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
- package/dist/cjs/data-structures/graph/abstract-graph.d.ts +238 -233
- package/dist/cjs/data-structures/graph/abstract-graph.js +267 -237
- package/dist/cjs/data-structures/graph/abstract-graph.js.map +1 -1
- package/dist/cjs/data-structures/graph/directed-graph.d.ts +108 -224
- package/dist/cjs/data-structures/graph/directed-graph.js +146 -233
- package/dist/cjs/data-structures/graph/directed-graph.js.map +1 -1
- package/dist/cjs/data-structures/graph/map-graph.d.ts +49 -55
- package/dist/cjs/data-structures/graph/map-graph.js +56 -59
- package/dist/cjs/data-structures/graph/map-graph.js.map +1 -1
- package/dist/cjs/data-structures/graph/undirected-graph.d.ts +103 -146
- package/dist/cjs/data-structures/graph/undirected-graph.js +129 -149
- package/dist/cjs/data-structures/graph/undirected-graph.js.map +1 -1
- package/dist/cjs/data-structures/hash/hash-map.d.ts +164 -338
- package/dist/cjs/data-structures/hash/hash-map.js +270 -457
- package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
- package/dist/cjs/data-structures/heap/heap.d.ts +214 -289
- package/dist/cjs/data-structures/heap/heap.js +340 -349
- package/dist/cjs/data-structures/heap/heap.js.map +1 -1
- package/dist/cjs/data-structures/heap/max-heap.d.ts +11 -47
- package/dist/cjs/data-structures/heap/max-heap.js +11 -66
- package/dist/cjs/data-structures/heap/max-heap.js.map +1 -1
- package/dist/cjs/data-structures/heap/min-heap.d.ts +12 -47
- package/dist/cjs/data-structures/heap/min-heap.js +11 -66
- package/dist/cjs/data-structures/heap/min-heap.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
- package/dist/cjs/data-structures/linked-list/doubly-linked-list.js +368 -494
- package/dist/cjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/singly-linked-list.d.ts +261 -310
- package/dist/cjs/data-structures/linked-list/singly-linked-list.js +447 -466
- package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/skip-linked-list.d.ts +0 -107
- package/dist/cjs/data-structures/linked-list/skip-linked-list.js +0 -100
- package/dist/cjs/data-structures/linked-list/skip-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
- package/dist/cjs/data-structures/priority-queue/max-priority-queue.js +11 -78
- package/dist/cjs/data-structures/priority-queue/max-priority-queue.js.map +1 -1
- package/dist/cjs/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
- package/dist/cjs/data-structures/priority-queue/min-priority-queue.js +10 -79
- package/dist/cjs/data-structures/priority-queue/min-priority-queue.js.map +1 -1
- package/dist/cjs/data-structures/priority-queue/priority-queue.d.ts +2 -61
- package/dist/cjs/data-structures/priority-queue/priority-queue.js +8 -83
- package/dist/cjs/data-structures/priority-queue/priority-queue.js.map +1 -1
- package/dist/cjs/data-structures/queue/deque.d.ts +227 -254
- package/dist/cjs/data-structures/queue/deque.js +309 -348
- package/dist/cjs/data-structures/queue/deque.js.map +1 -1
- package/dist/cjs/data-structures/queue/queue.d.ts +180 -201
- package/dist/cjs/data-structures/queue/queue.js +265 -248
- package/dist/cjs/data-structures/queue/queue.js.map +1 -1
- package/dist/cjs/data-structures/stack/stack.d.ts +124 -102
- package/dist/cjs/data-structures/stack/stack.js +181 -125
- package/dist/cjs/data-structures/stack/stack.js.map +1 -1
- package/dist/cjs/data-structures/trie/trie.d.ts +164 -165
- package/dist/cjs/data-structures/trie/trie.js +189 -172
- package/dist/cjs/data-structures/trie/trie.js.map +1 -1
- package/dist/cjs/interfaces/binary-tree.d.ts +56 -6
- package/dist/cjs/interfaces/graph.d.ts +16 -0
- package/dist/cjs/types/data-structures/base/base.d.ts +1 -1
- package/dist/cjs/types/data-structures/graph/abstract-graph.d.ts +4 -0
- package/dist/cjs/types/utils/utils.d.ts +6 -6
- package/dist/cjs/utils/utils.d.ts +110 -49
- package/dist/cjs/utils/utils.js +148 -73
- package/dist/cjs/utils/utils.js.map +1 -1
- package/dist/esm/data-structures/base/iterable-element-base.d.ts +186 -83
- package/dist/esm/data-structures/base/iterable-element-base.js +155 -107
- package/dist/esm/data-structures/base/iterable-element-base.js.map +1 -1
- package/dist/esm/data-structures/base/iterable-entry-base.d.ts +95 -119
- package/dist/esm/data-structures/base/iterable-entry-base.js +59 -116
- package/dist/esm/data-structures/base/iterable-entry-base.js.map +1 -1
- package/dist/esm/data-structures/base/linear-base.d.ts +250 -192
- package/dist/esm/data-structures/base/linear-base.js +137 -274
- package/dist/esm/data-structures/base/linear-base.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
- package/dist/esm/data-structures/binary-tree/avl-tree-counter.js +171 -212
- package/dist/esm/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
- package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js +133 -94
- package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/avl-tree.d.ts +138 -149
- package/dist/esm/data-structures/binary-tree/avl-tree.js +206 -200
- package/dist/esm/data-structures/binary-tree/avl-tree.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/binary-tree.d.ts +476 -632
- package/dist/esm/data-structures/binary-tree/binary-tree.js +613 -885
- package/dist/esm/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/bst.d.ts +258 -306
- package/dist/esm/data-structures/binary-tree/bst.js +507 -487
- package/dist/esm/data-structures/binary-tree/bst.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/red-black-tree.d.ts +107 -179
- package/dist/esm/data-structures/binary-tree/red-black-tree.js +114 -215
- package/dist/esm/data-structures/binary-tree/red-black-tree.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/tree-counter.d.ts +132 -154
- package/dist/esm/data-structures/binary-tree/tree-counter.js +175 -209
- package/dist/esm/data-structures/binary-tree/tree-counter.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
- package/dist/esm/data-structures/binary-tree/tree-multi-map.js +103 -92
- package/dist/esm/data-structures/binary-tree/tree-multi-map.js.map +1 -1
- package/dist/esm/data-structures/graph/abstract-graph.d.ts +238 -233
- package/dist/esm/data-structures/graph/abstract-graph.js +267 -237
- package/dist/esm/data-structures/graph/abstract-graph.js.map +1 -1
- package/dist/esm/data-structures/graph/directed-graph.d.ts +108 -224
- package/dist/esm/data-structures/graph/directed-graph.js +145 -233
- package/dist/esm/data-structures/graph/directed-graph.js.map +1 -1
- package/dist/esm/data-structures/graph/map-graph.d.ts +49 -55
- package/dist/esm/data-structures/graph/map-graph.js +56 -59
- package/dist/esm/data-structures/graph/map-graph.js.map +1 -1
- package/dist/esm/data-structures/graph/undirected-graph.d.ts +103 -146
- package/dist/esm/data-structures/graph/undirected-graph.js +128 -149
- package/dist/esm/data-structures/graph/undirected-graph.js.map +1 -1
- package/dist/esm/data-structures/hash/hash-map.d.ts +164 -338
- package/dist/esm/data-structures/hash/hash-map.js +270 -457
- package/dist/esm/data-structures/hash/hash-map.js.map +1 -1
- package/dist/esm/data-structures/heap/heap.d.ts +214 -289
- package/dist/esm/data-structures/heap/heap.js +329 -349
- package/dist/esm/data-structures/heap/heap.js.map +1 -1
- package/dist/esm/data-structures/heap/max-heap.d.ts +11 -47
- package/dist/esm/data-structures/heap/max-heap.js +11 -66
- package/dist/esm/data-structures/heap/max-heap.js.map +1 -1
- package/dist/esm/data-structures/heap/min-heap.d.ts +12 -47
- package/dist/esm/data-structures/heap/min-heap.js +11 -66
- package/dist/esm/data-structures/heap/min-heap.js.map +1 -1
- package/dist/esm/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
- package/dist/esm/data-structures/linked-list/doubly-linked-list.js +368 -495
- package/dist/esm/data-structures/linked-list/doubly-linked-list.js.map +1 -1
- package/dist/esm/data-structures/linked-list/singly-linked-list.d.ts +261 -310
- package/dist/esm/data-structures/linked-list/singly-linked-list.js +448 -467
- package/dist/esm/data-structures/linked-list/singly-linked-list.js.map +1 -1
- package/dist/esm/data-structures/linked-list/skip-linked-list.d.ts +0 -107
- package/dist/esm/data-structures/linked-list/skip-linked-list.js +0 -100
- package/dist/esm/data-structures/linked-list/skip-linked-list.js.map +1 -1
- package/dist/esm/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
- package/dist/esm/data-structures/priority-queue/max-priority-queue.js +11 -78
- package/dist/esm/data-structures/priority-queue/max-priority-queue.js.map +1 -1
- package/dist/esm/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
- package/dist/esm/data-structures/priority-queue/min-priority-queue.js +10 -79
- package/dist/esm/data-structures/priority-queue/min-priority-queue.js.map +1 -1
- package/dist/esm/data-structures/priority-queue/priority-queue.d.ts +2 -61
- package/dist/esm/data-structures/priority-queue/priority-queue.js +8 -83
- package/dist/esm/data-structures/priority-queue/priority-queue.js.map +1 -1
- package/dist/esm/data-structures/queue/deque.d.ts +227 -254
- package/dist/esm/data-structures/queue/deque.js +313 -348
- package/dist/esm/data-structures/queue/deque.js.map +1 -1
- package/dist/esm/data-structures/queue/queue.d.ts +180 -201
- package/dist/esm/data-structures/queue/queue.js +263 -248
- package/dist/esm/data-structures/queue/queue.js.map +1 -1
- package/dist/esm/data-structures/stack/stack.d.ts +124 -102
- package/dist/esm/data-structures/stack/stack.js +181 -125
- package/dist/esm/data-structures/stack/stack.js.map +1 -1
- package/dist/esm/data-structures/trie/trie.d.ts +164 -165
- package/dist/esm/data-structures/trie/trie.js +193 -172
- package/dist/esm/data-structures/trie/trie.js.map +1 -1
- package/dist/esm/interfaces/binary-tree.d.ts +56 -6
- package/dist/esm/interfaces/graph.d.ts +16 -0
- package/dist/esm/types/data-structures/base/base.d.ts +1 -1
- package/dist/esm/types/data-structures/graph/abstract-graph.d.ts +4 -0
- package/dist/esm/types/utils/utils.d.ts +6 -6
- package/dist/esm/utils/utils.d.ts +110 -49
- package/dist/esm/utils/utils.js +139 -68
- package/dist/esm/utils/utils.js.map +1 -1
- package/dist/umd/data-structure-typed.js +4737 -6525
- package/dist/umd/data-structure-typed.min.js +8 -6
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +3 -4
- package/src/data-structures/base/iterable-element-base.ts +238 -115
- package/src/data-structures/base/iterable-entry-base.ts +96 -120
- package/src/data-structures/base/linear-base.ts +271 -277
- package/src/data-structures/binary-tree/avl-tree-counter.ts +198 -216
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +192 -101
- package/src/data-structures/binary-tree/avl-tree.ts +239 -206
- package/src/data-structures/binary-tree/binary-tree.ts +677 -901
- package/src/data-structures/binary-tree/bst.ts +568 -570
- package/src/data-structures/binary-tree/red-black-tree.ts +161 -222
- package/src/data-structures/binary-tree/tree-counter.ts +199 -218
- package/src/data-structures/binary-tree/tree-multi-map.ts +131 -97
- package/src/data-structures/graph/abstract-graph.ts +339 -264
- package/src/data-structures/graph/directed-graph.ts +146 -236
- package/src/data-structures/graph/map-graph.ts +63 -60
- package/src/data-structures/graph/undirected-graph.ts +129 -152
- package/src/data-structures/hash/hash-map.ts +274 -496
- package/src/data-structures/heap/heap.ts +389 -402
- package/src/data-structures/heap/max-heap.ts +12 -76
- package/src/data-structures/heap/min-heap.ts +13 -76
- package/src/data-structures/linked-list/doubly-linked-list.ts +426 -530
- package/src/data-structures/linked-list/singly-linked-list.ts +495 -517
- package/src/data-structures/linked-list/skip-linked-list.ts +1 -108
- package/src/data-structures/priority-queue/max-priority-queue.ts +12 -87
- package/src/data-structures/priority-queue/min-priority-queue.ts +11 -88
- package/src/data-structures/priority-queue/priority-queue.ts +3 -92
- package/src/data-structures/queue/deque.ts +381 -357
- package/src/data-structures/queue/queue.ts +310 -264
- package/src/data-structures/stack/stack.ts +217 -131
- package/src/data-structures/trie/trie.ts +240 -175
- package/src/interfaces/binary-tree.ts +240 -6
- package/src/interfaces/graph.ts +37 -0
- package/src/types/data-structures/base/base.ts +5 -5
- package/src/types/data-structures/graph/abstract-graph.ts +5 -0
- package/src/types/utils/utils.ts +9 -5
- package/src/utils/utils.ts +152 -86
- package/test/integration/index.html +1 -1
- package/test/performance/benchmark-runner.ts +528 -0
- package/test/performance/reportor.mjs +43 -43
- package/test/performance/runner-config.json +39 -0
- package/test/performance/single-suite-runner.ts +69 -0
- package/test/unit/data-structures/binary-tree/avl-tree-counter.test.ts +3 -3
- package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +5 -5
- package/test/unit/data-structures/binary-tree/avl-tree.test.ts +4 -4
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +350 -90
- package/test/unit/data-structures/binary-tree/bst.test.ts +84 -5
- package/test/unit/data-structures/binary-tree/red-black-tree.test.ts +2 -2
- package/test/unit/data-structures/binary-tree/tree-counter.test.ts +25 -24
- package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +3 -3
- package/test/unit/data-structures/graph/abstract-graph.test.ts +0 -4
- package/test/unit/data-structures/graph/directed-graph.test.ts +1 -1
- package/test/unit/data-structures/heap/heap.test.ts +14 -21
- package/test/unit/data-structures/heap/max-heap.test.ts +5 -9
- package/test/unit/data-structures/heap/min-heap.test.ts +1 -4
- package/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +14 -14
- package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +0 -7
- package/test/unit/data-structures/priority-queue/max-priority-queue.test.ts +8 -11
- package/test/unit/data-structures/priority-queue/min-priority-queue.test.ts +1 -4
- package/test/unit/data-structures/priority-queue/priority-queue.test.ts +1 -4
- package/test/unit/data-structures/queue/queue.test.ts +4 -5
- package/test/unit/utils/utils.test.ts +0 -1
- package/test/performance/data-structures/binary-tree/avl-tree.test.mjs +0 -71
- package/test/performance/data-structures/binary-tree/red-black-tree.test.mjs +0 -81
|
@@ -1,6 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* data-structure-typed
|
|
3
|
+
*
|
|
4
|
+
* @author Pablo Zeng
|
|
5
|
+
* @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
|
|
6
|
+
* @license MIT License
|
|
7
|
+
*/
|
|
1
8
|
import { IterableEntryBase } from '../base';
|
|
2
9
|
import { isWeakKey, rangeCheck } from '../../utils';
|
|
3
10
|
/**
|
|
11
|
+
* Hash-based map. Supports object keys and custom hashing; offers O(1) average set/get/has.
|
|
12
|
+
* @remarks Time O(1), Space O(1)
|
|
13
|
+
* @template K
|
|
14
|
+
* @template V
|
|
15
|
+
* @template R
|
|
4
16
|
* 1. Key-Value Pair Storage: HashMap stores key-value pairs. Each key map to a value.
|
|
5
17
|
* 2. Fast Lookup: It's used when you need to quickly find, insert, or delete entries based on a key.
|
|
6
18
|
* 3. Unique Keys: Keys are unique.
|
|
@@ -55,11 +67,11 @@ import { isWeakKey, rangeCheck } from '../../utils';
|
|
|
55
67
|
*/
|
|
56
68
|
export class HashMap extends IterableEntryBase {
|
|
57
69
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* @param entryOrRawElements -
|
|
61
|
-
*
|
|
62
|
-
* @
|
|
70
|
+
* Create a HashMap and optionally bulk-insert entries.
|
|
71
|
+
* @remarks Time O(N), Space O(N)
|
|
72
|
+
* @param [entryOrRawElements] - Iterable of entries or raw elements to insert.
|
|
73
|
+
* @param [options] - Options: hash function and optional record-to-entry converter.
|
|
74
|
+
* @returns New HashMap instance.
|
|
63
75
|
*/
|
|
64
76
|
constructor(entryOrRawElements = [], options) {
|
|
65
77
|
super();
|
|
@@ -70,82 +82,66 @@ export class HashMap extends IterableEntryBase {
|
|
|
70
82
|
if (toEntryFn)
|
|
71
83
|
this._toEntryFn = toEntryFn;
|
|
72
84
|
}
|
|
73
|
-
if (entryOrRawElements)
|
|
85
|
+
if (entryOrRawElements)
|
|
74
86
|
this.setMany(entryOrRawElements);
|
|
75
|
-
}
|
|
76
87
|
}
|
|
77
88
|
_store = {};
|
|
78
89
|
/**
|
|
79
|
-
*
|
|
80
|
-
* @
|
|
81
|
-
*
|
|
90
|
+
* Get the internal store for non-object keys.
|
|
91
|
+
* @remarks Time O(1), Space O(1)
|
|
92
|
+
* @returns Internal record of string→{key,value}.
|
|
82
93
|
*/
|
|
83
94
|
get store() {
|
|
84
95
|
return this._store;
|
|
85
96
|
}
|
|
86
97
|
_objMap = new Map();
|
|
87
98
|
/**
|
|
88
|
-
*
|
|
89
|
-
* @
|
|
90
|
-
*
|
|
99
|
+
* Get the internal Map used for object/function keys.
|
|
100
|
+
* @remarks Time O(1), Space O(1)
|
|
101
|
+
* @returns Map of object→value.
|
|
91
102
|
*/
|
|
92
103
|
get objMap() {
|
|
93
104
|
return this._objMap;
|
|
94
105
|
}
|
|
95
106
|
_toEntryFn;
|
|
96
107
|
/**
|
|
97
|
-
*
|
|
98
|
-
* @
|
|
108
|
+
* Get the raw→entry converter function if present.
|
|
109
|
+
* @remarks Time O(1), Space O(1)
|
|
110
|
+
* @returns Converter function or undefined.
|
|
99
111
|
*/
|
|
100
112
|
get toEntryFn() {
|
|
101
113
|
return this._toEntryFn;
|
|
102
114
|
}
|
|
103
115
|
_size = 0;
|
|
104
116
|
/**
|
|
105
|
-
*
|
|
106
|
-
* @
|
|
117
|
+
* Get the number of distinct keys stored.
|
|
118
|
+
* @remarks Time O(1), Space O(1)
|
|
119
|
+
* @returns Current size.
|
|
107
120
|
*/
|
|
108
121
|
get size() {
|
|
109
122
|
return this._size;
|
|
110
123
|
}
|
|
111
124
|
_hashFn = (key) => String(key);
|
|
112
125
|
/**
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* @return The hash function
|
|
126
|
+
* Get the current hash function for non-object keys.
|
|
127
|
+
* @remarks Time O(1), Space O(1)
|
|
128
|
+
* @returns Hash function.
|
|
117
129
|
*/
|
|
118
130
|
get hashFn() {
|
|
119
131
|
return this._hashFn;
|
|
120
132
|
}
|
|
121
133
|
/**
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
* The function checks if a given element is an array with exactly two elements.
|
|
126
|
-
* @param {any} rawElement - The `rawElement` parameter is of type `any`, which means it can be any
|
|
127
|
-
* data type.
|
|
128
|
-
* @returns a boolean value.
|
|
129
|
-
*/
|
|
130
|
-
isEntry(rawElement) {
|
|
131
|
-
return Array.isArray(rawElement) && rawElement.length === 2;
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Time Complexity: O(1)
|
|
135
|
-
* Space Complexity: O(1)
|
|
136
|
-
*
|
|
137
|
-
* The function checks if the size of an object is equal to zero and returns a boolean value.
|
|
138
|
-
* @returns A boolean value indicating whether the size of the object is 0 or not.
|
|
134
|
+
* Check whether the map is empty.
|
|
135
|
+
* @remarks Time O(1), Space O(1)
|
|
136
|
+
* @returns True if size is 0.
|
|
139
137
|
*/
|
|
140
138
|
isEmpty() {
|
|
141
139
|
return this._size === 0;
|
|
142
140
|
}
|
|
143
141
|
/**
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
* The clear() function resets the state of an object by clearing its internal store, object map, and
|
|
148
|
-
* size.
|
|
142
|
+
* Remove all entries and reset counters.
|
|
143
|
+
* @remarks Time O(N), Space O(1)
|
|
144
|
+
* @returns void
|
|
149
145
|
*/
|
|
150
146
|
clear() {
|
|
151
147
|
this._store = {};
|
|
@@ -153,215 +149,181 @@ export class HashMap extends IterableEntryBase {
|
|
|
153
149
|
this._size = 0;
|
|
154
150
|
}
|
|
155
151
|
/**
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
*
|
|
165
|
-
*
|
|
152
|
+
* Type guard: check if a raw value is a [key, value] entry.
|
|
153
|
+
* @remarks Time O(1), Space O(1)
|
|
154
|
+
* @returns True if the value is a 2-tuple.
|
|
155
|
+
*/
|
|
156
|
+
isEntry(rawElement) {
|
|
157
|
+
return Array.isArray(rawElement) && rawElement.length === 2;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Insert or replace a single entry.
|
|
161
|
+
* @remarks Time O(1), Space O(1)
|
|
162
|
+
* @param key - Key.
|
|
163
|
+
* @param value - Value.
|
|
164
|
+
* @returns True when the operation succeeds.
|
|
166
165
|
*/
|
|
167
166
|
set(key, value) {
|
|
168
167
|
if (this._isObjKey(key)) {
|
|
169
|
-
if (!this.objMap.has(key))
|
|
168
|
+
if (!this.objMap.has(key))
|
|
170
169
|
this._size++;
|
|
171
|
-
}
|
|
172
170
|
this.objMap.set(key, value);
|
|
173
171
|
}
|
|
174
172
|
else {
|
|
175
173
|
const strKey = this._getNoObjKey(key);
|
|
176
|
-
if (this.store[strKey] === undefined)
|
|
174
|
+
if (this.store[strKey] === undefined)
|
|
177
175
|
this._size++;
|
|
178
|
-
}
|
|
179
176
|
this._store[strKey] = { key, value };
|
|
180
177
|
}
|
|
181
178
|
return true;
|
|
182
179
|
}
|
|
183
180
|
/**
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
* pair using a mapping function, and sets each key-value pair in the current object.
|
|
189
|
-
* @param entryOrRawElements - The `entryOrRawElements` parameter is an iterable collection of elements of a type
|
|
190
|
-
* `T`.
|
|
191
|
-
* @returns The `setMany` function is returning an array of booleans.
|
|
181
|
+
* Insert many entries from an iterable.
|
|
182
|
+
* @remarks Time O(N), Space O(N)
|
|
183
|
+
* @param entryOrRawElements - Iterable of entries or raw elements to insert.
|
|
184
|
+
* @returns Array of per-entry results.
|
|
192
185
|
*/
|
|
193
186
|
setMany(entryOrRawElements) {
|
|
194
187
|
const results = [];
|
|
195
188
|
for (const rawEle of entryOrRawElements) {
|
|
196
189
|
let key, value;
|
|
197
|
-
if (this.isEntry(rawEle))
|
|
198
|
-
key = rawEle
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
else if (this._toEntryFn) {
|
|
202
|
-
const item = this._toEntryFn(rawEle);
|
|
203
|
-
key = item[0];
|
|
204
|
-
value = item[1];
|
|
205
|
-
}
|
|
190
|
+
if (this.isEntry(rawEle))
|
|
191
|
+
[key, value] = rawEle;
|
|
192
|
+
else if (this._toEntryFn)
|
|
193
|
+
[key, value] = this._toEntryFn(rawEle);
|
|
206
194
|
if (key !== undefined && value !== undefined)
|
|
207
195
|
results.push(this.set(key, value));
|
|
208
196
|
}
|
|
209
197
|
return results;
|
|
210
198
|
}
|
|
211
199
|
/**
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
* a string map.
|
|
217
|
-
* @param {K} key - The `key` parameter is the key used to retrieve a value from the map. It can be
|
|
218
|
-
* of any type, but it should be compatible with the key type used when the map was created.
|
|
219
|
-
* @returns The method `get(key: K)` returns a value of type `V` if the key exists in the `_objMap`
|
|
220
|
-
* or `_store`, otherwise it returns `undefined`.
|
|
200
|
+
* Get the value for a key.
|
|
201
|
+
* @remarks Time O(1), Space O(1)
|
|
202
|
+
* @param key - Key to look up.
|
|
203
|
+
* @returns Value or undefined.
|
|
221
204
|
*/
|
|
222
205
|
get(key) {
|
|
223
|
-
if (this._isObjKey(key))
|
|
206
|
+
if (this._isObjKey(key))
|
|
224
207
|
return this.objMap.get(key);
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
const strKey = this._getNoObjKey(key);
|
|
228
|
-
return this._store[strKey]?.value;
|
|
229
|
-
}
|
|
208
|
+
const strKey = this._getNoObjKey(key);
|
|
209
|
+
return this._store[strKey]?.value;
|
|
230
210
|
}
|
|
231
211
|
/**
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
* is an object key or not.
|
|
237
|
-
* @param {K} key - The parameter "key" is of type K, which means it can be any type.
|
|
238
|
-
* @returns The `has` method is returning a boolean value.
|
|
212
|
+
* Check if a key exists.
|
|
213
|
+
* @remarks Time O(1), Space O(1)
|
|
214
|
+
* @param key - Key to test.
|
|
215
|
+
* @returns True if present.
|
|
239
216
|
*/
|
|
240
217
|
has(key) {
|
|
241
|
-
if (this._isObjKey(key))
|
|
218
|
+
if (this._isObjKey(key))
|
|
242
219
|
return this.objMap.has(key);
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const strKey = this._getNoObjKey(key);
|
|
246
|
-
return strKey in this.store;
|
|
247
|
-
}
|
|
220
|
+
const strKey = this._getNoObjKey(key);
|
|
221
|
+
return strKey in this.store;
|
|
248
222
|
}
|
|
249
223
|
/**
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
* @param {K} key - The `key` parameter is the key of the element that you want to delete from the
|
|
255
|
-
* data structure.
|
|
256
|
-
* @returns The `delete` method returns a boolean value. It returns `true` if the key was
|
|
257
|
-
* successfully deleted from the map, and `false` if the key was not found in the map.
|
|
224
|
+
* Delete an entry by key.
|
|
225
|
+
* @remarks Time O(1), Space O(1)
|
|
226
|
+
* @param key - Key to delete.
|
|
227
|
+
* @returns True if the key was found and removed.
|
|
258
228
|
*/
|
|
259
229
|
delete(key) {
|
|
260
230
|
if (this._isObjKey(key)) {
|
|
261
|
-
if (this.objMap.has(key))
|
|
231
|
+
if (this.objMap.has(key))
|
|
262
232
|
this._size--;
|
|
263
|
-
}
|
|
264
233
|
return this.objMap.delete(key);
|
|
265
234
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
return true;
|
|
272
|
-
}
|
|
273
|
-
return false;
|
|
235
|
+
const strKey = this._getNoObjKey(key);
|
|
236
|
+
if (strKey in this.store) {
|
|
237
|
+
delete this.store[strKey];
|
|
238
|
+
this._size--;
|
|
239
|
+
return true;
|
|
274
240
|
}
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Replace the hash function and rehash the non-object store.
|
|
245
|
+
* @remarks Time O(N), Space O(N)
|
|
246
|
+
* @param fn - New hash function for non-object keys.
|
|
247
|
+
* @returns This map instance.
|
|
248
|
+
*/
|
|
249
|
+
setHashFn(fn) {
|
|
250
|
+
if (this._hashFn === fn)
|
|
251
|
+
return this;
|
|
252
|
+
this._hashFn = fn;
|
|
253
|
+
this._rehashNoObj();
|
|
254
|
+
return this;
|
|
275
255
|
}
|
|
276
256
|
/**
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
* The clone function creates a new HashMap with the same key-value pairs as
|
|
281
|
-
* this one. The clone function is useful for creating a copy of an existing
|
|
282
|
-
* HashMap, and then modifying that copy without affecting the original.
|
|
283
|
-
*
|
|
284
|
-
* @return A new hashmap with the same values as this one
|
|
257
|
+
* Deep clone this map, preserving hashing behavior.
|
|
258
|
+
* @remarks Time O(N), Space O(N)
|
|
259
|
+
* @returns A new map with the same content.
|
|
285
260
|
*/
|
|
286
261
|
clone() {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
*
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
* key
|
|
295
|
-
* @param
|
|
296
|
-
*
|
|
297
|
-
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
|
298
|
-
* to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will
|
|
299
|
-
* be passed as the `this` value to the `callbackfn` function. If `thisArg
|
|
300
|
-
* @returns The `map` method is returning a new `HashMap` object with the transformed values based on
|
|
301
|
-
* the provided callback function.
|
|
262
|
+
const opts = { hashFn: this._hashFn, toEntryFn: this._toEntryFn };
|
|
263
|
+
return this._createLike(this, opts);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Map values to a new map with the same keys.
|
|
267
|
+
* @remarks Time O(N), Space O(N)
|
|
268
|
+
* @template VM
|
|
269
|
+
* @param callbackfn - Mapping function (key, value, index, map) → newValue.
|
|
270
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
271
|
+
* @returns A new map with transformed values.
|
|
302
272
|
*/
|
|
303
273
|
map(callbackfn, thisArg) {
|
|
304
|
-
const
|
|
274
|
+
const out = this._createLike();
|
|
305
275
|
let index = 0;
|
|
306
|
-
for (const [key, value] of this)
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
* Time
|
|
313
|
-
*
|
|
314
|
-
*
|
|
315
|
-
*
|
|
316
|
-
* that satisfy a given predicate function.
|
|
317
|
-
* @param predicate - The predicate parameter is a function that takes four arguments: value, key,
|
|
318
|
-
* index, and map. It is used to determine whether an element should be included in the filtered map
|
|
319
|
-
* or not. The function should return a boolean value - true if the element should be included, and
|
|
320
|
-
* false otherwise.
|
|
321
|
-
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
|
322
|
-
* to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be
|
|
323
|
-
* passed as the `this` value to the `predicate` function. If `thisArg` is
|
|
324
|
-
* @returns The `filter` method is returning a new `HashMap` object that contains the key-value pairs
|
|
325
|
-
* from the original `HashMap` that pass the provided `predicate` function.
|
|
276
|
+
for (const [key, value] of this)
|
|
277
|
+
out.set(key, callbackfn.call(thisArg, key, value, index++, this));
|
|
278
|
+
return out;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Filter entries into a new map.
|
|
282
|
+
* @remarks Time O(N), Space O(N)
|
|
283
|
+
* @param predicate - Predicate (key, value, index, map) → boolean.
|
|
284
|
+
* @param [thisArg] - Value for `this` inside the predicate.
|
|
285
|
+
* @returns A new map containing entries that satisfied the predicate.
|
|
326
286
|
*/
|
|
327
287
|
filter(predicate, thisArg) {
|
|
328
|
-
const
|
|
288
|
+
const out = this._createLike();
|
|
329
289
|
let index = 0;
|
|
330
|
-
for (const [key, value] of this)
|
|
331
|
-
if (predicate.call(thisArg, key, value, index++, this))
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
}
|
|
335
|
-
return filteredMap;
|
|
290
|
+
for (const [key, value] of this)
|
|
291
|
+
if (predicate.call(thisArg, key, value, index++, this))
|
|
292
|
+
out.set(key, value);
|
|
293
|
+
return out;
|
|
336
294
|
}
|
|
337
295
|
/**
|
|
338
|
-
*
|
|
339
|
-
*
|
|
296
|
+
* (Protected) Create a like-kind instance and seed it from an iterable.
|
|
297
|
+
* @remarks Time O(N), Space O(N)
|
|
298
|
+
* @template TK
|
|
299
|
+
* @template TV
|
|
300
|
+
* @template TR
|
|
301
|
+
* @param [entries] - Iterable used to seed the new map.
|
|
302
|
+
* @param [options] - Options forwarded to the constructor.
|
|
303
|
+
* @returns A like-kind map instance.
|
|
340
304
|
*/
|
|
305
|
+
_createLike(entries = [], options) {
|
|
306
|
+
const Ctor = this.constructor;
|
|
307
|
+
return new Ctor(entries, options);
|
|
308
|
+
}
|
|
309
|
+
_rehashNoObj() {
|
|
310
|
+
const fresh = {};
|
|
311
|
+
for (const { key, value } of Object.values(this._store)) {
|
|
312
|
+
const sk = this._getNoObjKey(key);
|
|
313
|
+
fresh[sk] = { key, value };
|
|
314
|
+
}
|
|
315
|
+
this._store = fresh;
|
|
316
|
+
}
|
|
341
317
|
*_getIterator() {
|
|
342
|
-
for (const node of Object.values(this.store))
|
|
318
|
+
for (const node of Object.values(this.store))
|
|
343
319
|
yield [node.key, node.value];
|
|
344
|
-
|
|
345
|
-
for (const node of this.objMap) {
|
|
320
|
+
for (const node of this.objMap)
|
|
346
321
|
yield node;
|
|
347
|
-
}
|
|
348
322
|
}
|
|
349
|
-
/**
|
|
350
|
-
* The function checks if a given key is an object or a function.
|
|
351
|
-
* @param {any} key - The parameter "key" can be of any type.
|
|
352
|
-
* @returns a boolean value.
|
|
353
|
-
*/
|
|
354
323
|
_isObjKey(key) {
|
|
355
324
|
const keyType = typeof key;
|
|
356
325
|
return (keyType === 'object' || keyType === 'function') && key !== null;
|
|
357
326
|
}
|
|
358
|
-
/**
|
|
359
|
-
* The function `_getNoObjKey` takes a key and returns a string representation of the key, handling
|
|
360
|
-
* different types of keys.
|
|
361
|
-
* @param {K} key - The `key` parameter is of type `K`, which represents the type of the key being
|
|
362
|
-
* passed to the `_getNoObjKey` function.
|
|
363
|
-
* @returns a string value.
|
|
364
|
-
*/
|
|
365
327
|
_getNoObjKey(key) {
|
|
366
328
|
const keyType = typeof key;
|
|
367
329
|
let strKey;
|
|
@@ -370,7 +332,6 @@ export class HashMap extends IterableEntryBase {
|
|
|
370
332
|
}
|
|
371
333
|
else {
|
|
372
334
|
if (keyType === 'number') {
|
|
373
|
-
// TODO numeric key should has its own hash
|
|
374
335
|
strKey = key;
|
|
375
336
|
}
|
|
376
337
|
else {
|
|
@@ -381,20 +342,21 @@ export class HashMap extends IterableEntryBase {
|
|
|
381
342
|
}
|
|
382
343
|
}
|
|
383
344
|
/**
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
*
|
|
345
|
+
* Hash-based map that preserves insertion order via a doubly-linked list.
|
|
346
|
+
* @remarks Time O(1), Space O(1)
|
|
347
|
+
* @template K
|
|
348
|
+
* @template V
|
|
349
|
+
* @template R
|
|
350
|
+
* @example examples will be generated by unit test
|
|
387
351
|
*/
|
|
388
352
|
export class LinkedHashMap extends IterableEntryBase {
|
|
389
353
|
_sentinel;
|
|
390
354
|
/**
|
|
391
|
-
*
|
|
392
|
-
* @
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
* @param [options] - The `options` parameter is an optional object that can contain the following
|
|
397
|
-
* properties:
|
|
355
|
+
* Create a LinkedHashMap and optionally bulk-insert entries.
|
|
356
|
+
* @remarks Time O(N), Space O(N)
|
|
357
|
+
* @param [entryOrRawElements] - Iterable of entries or raw elements to insert.
|
|
358
|
+
* @param [options] - Options: hash functions and optional record-to-entry converter.
|
|
359
|
+
* @returns New LinkedHashMap instance.
|
|
398
360
|
*/
|
|
399
361
|
constructor(entryOrRawElements = [], options) {
|
|
400
362
|
super();
|
|
@@ -406,96 +368,73 @@ export class LinkedHashMap extends IterableEntryBase {
|
|
|
406
368
|
this._hashFn = hashFn;
|
|
407
369
|
if (objHashFn)
|
|
408
370
|
this._objHashFn = objHashFn;
|
|
409
|
-
if (toEntryFn)
|
|
371
|
+
if (toEntryFn)
|
|
410
372
|
this._toEntryFn = toEntryFn;
|
|
411
|
-
}
|
|
412
373
|
}
|
|
413
|
-
if (entryOrRawElements)
|
|
374
|
+
if (entryOrRawElements)
|
|
414
375
|
this.setMany(entryOrRawElements);
|
|
415
|
-
}
|
|
416
376
|
}
|
|
417
377
|
_hashFn = (key) => String(key);
|
|
418
|
-
/**
|
|
419
|
-
* The function returns the hash function used for generating a hash value for a given key.
|
|
420
|
-
* @returns The hash function that takes a key of type K and returns a string.
|
|
421
|
-
*/
|
|
422
378
|
get hashFn() {
|
|
423
379
|
return this._hashFn;
|
|
424
380
|
}
|
|
425
381
|
_objHashFn = (key) => key;
|
|
426
382
|
/**
|
|
427
|
-
*
|
|
428
|
-
* @
|
|
383
|
+
* Get the hash function for object/weak keys.
|
|
384
|
+
* @remarks Time O(1), Space O(1)
|
|
385
|
+
* @returns Object-hash function.
|
|
429
386
|
*/
|
|
430
387
|
get objHashFn() {
|
|
431
388
|
return this._objHashFn;
|
|
432
389
|
}
|
|
433
390
|
_noObjMap = {};
|
|
434
391
|
/**
|
|
435
|
-
*
|
|
436
|
-
* @
|
|
437
|
-
*
|
|
438
|
-
* values of type V or undefined.
|
|
392
|
+
* Get the internal record for non-object keys.
|
|
393
|
+
* @remarks Time O(1), Space O(1)
|
|
394
|
+
* @returns Record of hash→node.
|
|
439
395
|
*/
|
|
440
396
|
get noObjMap() {
|
|
441
397
|
return this._noObjMap;
|
|
442
398
|
}
|
|
443
399
|
_objMap = new WeakMap();
|
|
444
|
-
/**
|
|
445
|
-
* The function returns the WeakMap object used to map objects to HashMapLinkedNode instances.
|
|
446
|
-
* @returns The `objMap` property is being returned.
|
|
447
|
-
*/
|
|
448
400
|
get objMap() {
|
|
449
401
|
return this._objMap;
|
|
450
402
|
}
|
|
451
403
|
_head;
|
|
452
404
|
/**
|
|
453
|
-
*
|
|
454
|
-
* @
|
|
455
|
-
*
|
|
405
|
+
* Get the head node (first entry) sentinel link.
|
|
406
|
+
* @remarks Time O(1), Space O(1)
|
|
407
|
+
* @returns Head node or sentinel.
|
|
456
408
|
*/
|
|
457
409
|
get head() {
|
|
458
410
|
return this._head;
|
|
459
411
|
}
|
|
460
412
|
_tail;
|
|
461
413
|
/**
|
|
462
|
-
*
|
|
463
|
-
* @
|
|
414
|
+
* Get the tail node (last entry) sentinel link.
|
|
415
|
+
* @remarks Time O(1), Space O(1)
|
|
416
|
+
* @returns Tail node or sentinel.
|
|
464
417
|
*/
|
|
465
418
|
get tail() {
|
|
466
419
|
return this._tail;
|
|
467
420
|
}
|
|
468
421
|
_toEntryFn = (rawElement) => {
|
|
469
422
|
if (this.isEntry(rawElement)) {
|
|
470
|
-
// TODO, For performance optimization, it may be necessary to only inspect the first element traversed.
|
|
471
423
|
return rawElement;
|
|
472
424
|
}
|
|
473
|
-
|
|
474
|
-
throw new Error("If the provided entryOrRawElements does not adhere to the [key, value] type format, the toEntryFn in the constructor's options parameter needs to specified.");
|
|
475
|
-
}
|
|
425
|
+
throw new Error('If `entryOrRawElements` does not adhere to [key,value], provide `options.toEntryFn` to transform raw records.');
|
|
476
426
|
};
|
|
477
|
-
/**
|
|
478
|
-
* The function returns the value of the _toEntryFn property.
|
|
479
|
-
* @returns The function being returned is `this._toEntryFn`.
|
|
480
|
-
*/
|
|
481
427
|
get toEntryFn() {
|
|
482
428
|
return this._toEntryFn;
|
|
483
429
|
}
|
|
484
430
|
_size = 0;
|
|
485
|
-
/**
|
|
486
|
-
* The function returns the size of an object.
|
|
487
|
-
* @returns The size of the object.
|
|
488
|
-
*/
|
|
489
431
|
get size() {
|
|
490
432
|
return this._size;
|
|
491
433
|
}
|
|
492
434
|
/**
|
|
493
|
-
*
|
|
494
|
-
*
|
|
495
|
-
*
|
|
496
|
-
* The function returns the key-value pair at the front of a data structure.
|
|
497
|
-
* @returns The front element of the data structure, represented as a tuple with a key (K) and a
|
|
498
|
-
* value (V).
|
|
435
|
+
* Get the first [key, value] pair.
|
|
436
|
+
* @remarks Time O(1), Space O(1)
|
|
437
|
+
* @returns First entry or undefined when empty.
|
|
499
438
|
*/
|
|
500
439
|
get first() {
|
|
501
440
|
if (this._size === 0)
|
|
@@ -503,12 +442,9 @@ export class LinkedHashMap extends IterableEntryBase {
|
|
|
503
442
|
return [this.head.key, this.head.value];
|
|
504
443
|
}
|
|
505
444
|
/**
|
|
506
|
-
*
|
|
507
|
-
*
|
|
508
|
-
*
|
|
509
|
-
* The function returns the key-value pair at the end of a data structure.
|
|
510
|
-
* @returns The method is returning an array containing the key-value pair of the tail element in the
|
|
511
|
-
* data structure.
|
|
445
|
+
* Get the last [key, value] pair.
|
|
446
|
+
* @remarks Time O(1), Space O(1)
|
|
447
|
+
* @returns Last entry or undefined when empty.
|
|
512
448
|
*/
|
|
513
449
|
get last() {
|
|
514
450
|
if (this._size === 0)
|
|
@@ -516,7 +452,9 @@ export class LinkedHashMap extends IterableEntryBase {
|
|
|
516
452
|
return [this.tail.key, this.tail.value];
|
|
517
453
|
}
|
|
518
454
|
/**
|
|
519
|
-
*
|
|
455
|
+
* Iterate from head → tail.
|
|
456
|
+
* @remarks Time O(N), Space O(1)
|
|
457
|
+
* @returns Iterator of [key, value].
|
|
520
458
|
*/
|
|
521
459
|
*begin() {
|
|
522
460
|
let node = this.head;
|
|
@@ -526,8 +464,9 @@ export class LinkedHashMap extends IterableEntryBase {
|
|
|
526
464
|
}
|
|
527
465
|
}
|
|
528
466
|
/**
|
|
529
|
-
*
|
|
530
|
-
*
|
|
467
|
+
* Iterate from tail → head.
|
|
468
|
+
* @remarks Time O(N), Space O(1)
|
|
469
|
+
* @returns Iterator of [key, value].
|
|
531
470
|
*/
|
|
532
471
|
*reverseBegin() {
|
|
533
472
|
let node = this.tail;
|
|
@@ -537,30 +476,23 @@ export class LinkedHashMap extends IterableEntryBase {
|
|
|
537
476
|
}
|
|
538
477
|
}
|
|
539
478
|
/**
|
|
540
|
-
*
|
|
541
|
-
*
|
|
542
|
-
*
|
|
543
|
-
*
|
|
544
|
-
*
|
|
545
|
-
* @param {K} key - The `key` parameter is the key to be set in the data structure. It can be of any
|
|
546
|
-
* type, but typically it is a string or symbol.
|
|
547
|
-
* @param {V} [value] - The `value` parameter is an optional parameter of type `V`. It represents the
|
|
548
|
-
* value associated with the key being set in the data structure.
|
|
549
|
-
* @returns the size of the data structure after the key-value pair has been set.
|
|
479
|
+
* Insert or replace a single entry; preserves insertion order.
|
|
480
|
+
* @remarks Time O(1), Space O(1)
|
|
481
|
+
* @param key - Key.
|
|
482
|
+
* @param [value] - Value.
|
|
483
|
+
* @returns True when the operation succeeds.
|
|
550
484
|
*/
|
|
551
485
|
set(key, value) {
|
|
552
486
|
let node;
|
|
553
|
-
const isNewKey = !this.has(key);
|
|
487
|
+
const isNewKey = !this.has(key);
|
|
554
488
|
if (isWeakKey(key)) {
|
|
555
489
|
const hash = this._objHashFn(key);
|
|
556
490
|
node = this.objMap.get(hash);
|
|
557
491
|
if (!node && isNewKey) {
|
|
558
|
-
// Create a new node
|
|
559
492
|
node = { key: hash, value, prev: this.tail, next: this._sentinel };
|
|
560
493
|
this.objMap.set(hash, node);
|
|
561
494
|
}
|
|
562
495
|
else if (node) {
|
|
563
|
-
// Update the value of an existing node
|
|
564
496
|
node.value = value;
|
|
565
497
|
}
|
|
566
498
|
}
|
|
@@ -571,19 +503,17 @@ export class LinkedHashMap extends IterableEntryBase {
|
|
|
571
503
|
this.noObjMap[hash] = node = { key, value, prev: this.tail, next: this._sentinel };
|
|
572
504
|
}
|
|
573
505
|
else if (node) {
|
|
574
|
-
// Update the value of an existing node
|
|
575
506
|
node.value = value;
|
|
576
507
|
}
|
|
577
508
|
}
|
|
578
509
|
if (node && isNewKey) {
|
|
579
|
-
// Update the head and tail of the linked list
|
|
580
510
|
if (this._size === 0) {
|
|
581
511
|
this._head = node;
|
|
582
512
|
this._sentinel.next = node;
|
|
583
513
|
}
|
|
584
514
|
else {
|
|
585
515
|
this.tail.next = node;
|
|
586
|
-
node.prev = this.tail;
|
|
516
|
+
node.prev = this.tail;
|
|
587
517
|
}
|
|
588
518
|
this._tail = node;
|
|
589
519
|
this._sentinel.prev = node;
|
|
@@ -591,259 +521,150 @@ export class LinkedHashMap extends IterableEntryBase {
|
|
|
591
521
|
}
|
|
592
522
|
return true;
|
|
593
523
|
}
|
|
594
|
-
/**
|
|
595
|
-
* Time Complexity: O(k)
|
|
596
|
-
* Space Complexity: O(k)
|
|
597
|
-
*
|
|
598
|
-
* The function `setMany` takes an iterable collection, converts each element into a key-value pair
|
|
599
|
-
* using a provided function, and sets each key-value pair in the current object, returning an array
|
|
600
|
-
* of booleans indicating the success of each set operation.
|
|
601
|
-
* @param entryOrRawElements - The entryOrRawElements parameter is an iterable collection of elements of type
|
|
602
|
-
* R.
|
|
603
|
-
* @returns The `setMany` function returns an array of booleans.
|
|
604
|
-
*/
|
|
605
524
|
setMany(entryOrRawElements) {
|
|
606
525
|
const results = [];
|
|
607
526
|
for (const rawEle of entryOrRawElements) {
|
|
608
527
|
let key, value;
|
|
609
|
-
if (this.isEntry(rawEle))
|
|
610
|
-
key = rawEle
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
else if (this._toEntryFn) {
|
|
614
|
-
const item = this._toEntryFn(rawEle);
|
|
615
|
-
key = item[0];
|
|
616
|
-
value = item[1];
|
|
617
|
-
}
|
|
528
|
+
if (this.isEntry(rawEle))
|
|
529
|
+
[key, value] = rawEle;
|
|
530
|
+
else if (this._toEntryFn)
|
|
531
|
+
[key, value] = this._toEntryFn(rawEle);
|
|
618
532
|
if (key !== undefined && value !== undefined)
|
|
619
533
|
results.push(this.set(key, value));
|
|
620
534
|
}
|
|
621
535
|
return results;
|
|
622
536
|
}
|
|
623
|
-
/**
|
|
624
|
-
* Time Complexity: O(1)
|
|
625
|
-
* Space Complexity: O(1)
|
|
626
|
-
*
|
|
627
|
-
* The function checks if a given key exists in a map, using different logic depending on whether the
|
|
628
|
-
* key is a weak key or not.
|
|
629
|
-
* @param {K} key - The `key` parameter is the key that is being checked for existence in the map.
|
|
630
|
-
* @returns The method `has` is returning a boolean value.
|
|
631
|
-
*/
|
|
632
537
|
has(key) {
|
|
633
538
|
if (isWeakKey(key)) {
|
|
634
539
|
const hash = this._objHashFn(key);
|
|
635
540
|
return this.objMap.has(hash);
|
|
636
541
|
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
return hash in this.noObjMap;
|
|
640
|
-
}
|
|
542
|
+
const hash = this._hashFn(key);
|
|
543
|
+
return hash in this.noObjMap;
|
|
641
544
|
}
|
|
642
|
-
/**
|
|
643
|
-
* Time Complexity: O(1)
|
|
644
|
-
* Space Complexity: O(1)
|
|
645
|
-
*
|
|
646
|
-
* The function `get` retrieves the value associated with a given key from a map, either by using the
|
|
647
|
-
* key directly or by using an index stored in the key object.
|
|
648
|
-
* @param {K} key - The `key` parameter is the key used to retrieve a value from the map. It can be
|
|
649
|
-
* of any type, but typically it is a string or symbol.
|
|
650
|
-
* @returns The value associated with the given key is being returned. If the key is an object key,
|
|
651
|
-
* the value is retrieved from the `_nodes` array using the index stored in the `OBJ_KEY_INDEX`
|
|
652
|
-
* property of the key. If the key is a string key, the value is retrieved from the `_noObjMap` object
|
|
653
|
-
* using the key itself. If the key is not found, `undefined` is
|
|
654
|
-
*/
|
|
655
545
|
get(key) {
|
|
656
546
|
if (isWeakKey(key)) {
|
|
657
547
|
const hash = this._objHashFn(key);
|
|
658
548
|
const node = this.objMap.get(hash);
|
|
659
549
|
return node ? node.value : undefined;
|
|
660
550
|
}
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
return node ? node.value : undefined;
|
|
665
|
-
}
|
|
551
|
+
const hash = this._hashFn(key);
|
|
552
|
+
const node = this.noObjMap[hash];
|
|
553
|
+
return node ? node.value : undefined;
|
|
666
554
|
}
|
|
667
555
|
/**
|
|
668
|
-
*
|
|
669
|
-
*
|
|
670
|
-
*
|
|
671
|
-
*
|
|
672
|
-
* @param {number} index - The index parameter is a number that represents the position of the
|
|
673
|
-
* element we want to retrieve from the data structure.
|
|
674
|
-
* @returns The method `at(index: number)` is returning an array containing the key-value pair at
|
|
675
|
-
* the specified index in the data structure. The key-value pair is represented as a tuple `[K, V]`,
|
|
676
|
-
* where `K` is the key and `V` is the value.
|
|
556
|
+
* Get the value at a given index in insertion order.
|
|
557
|
+
* @remarks Time O(N), Space O(1)
|
|
558
|
+
* @param index - Zero-based index.
|
|
559
|
+
* @returns Value at the index.
|
|
677
560
|
*/
|
|
678
561
|
at(index) {
|
|
679
562
|
rangeCheck(index, 0, this._size - 1);
|
|
680
563
|
let node = this.head;
|
|
681
|
-
while (index--)
|
|
564
|
+
while (index--)
|
|
682
565
|
node = node.next;
|
|
683
|
-
}
|
|
684
566
|
return node.value;
|
|
685
567
|
}
|
|
686
|
-
/**
|
|
687
|
-
* Time Complexity: O(1)
|
|
688
|
-
* Space Complexity: O(1)
|
|
689
|
-
*
|
|
690
|
-
* The `delete` function removes a key-value pair from a map-like data structure.
|
|
691
|
-
* @param {K} key - The `key` parameter is the key that you want to delete from the data structure.
|
|
692
|
-
* It can be of any type, but typically it is a string or an object.
|
|
693
|
-
* @returns a boolean value. It returns `true` if the deletion was successful, and `false` if the key
|
|
694
|
-
* was not found.
|
|
695
|
-
*/
|
|
696
568
|
delete(key) {
|
|
697
569
|
let node;
|
|
698
570
|
if (isWeakKey(key)) {
|
|
699
571
|
const hash = this._objHashFn(key);
|
|
700
|
-
// Get nodes from WeakMap
|
|
701
572
|
node = this.objMap.get(hash);
|
|
702
|
-
if (!node)
|
|
703
|
-
return false;
|
|
704
|
-
}
|
|
705
|
-
// Remove nodes from WeakMap
|
|
573
|
+
if (!node)
|
|
574
|
+
return false;
|
|
706
575
|
this.objMap.delete(hash);
|
|
707
576
|
}
|
|
708
577
|
else {
|
|
709
578
|
const hash = this._hashFn(key);
|
|
710
|
-
// Get nodes from noObjMap
|
|
711
579
|
node = this.noObjMap[hash];
|
|
712
|
-
if (!node)
|
|
713
|
-
return false;
|
|
714
|
-
}
|
|
715
|
-
// Remove nodes from orgMap
|
|
580
|
+
if (!node)
|
|
581
|
+
return false;
|
|
716
582
|
delete this.noObjMap[hash];
|
|
717
583
|
}
|
|
718
|
-
|
|
719
|
-
this._deleteNode(node);
|
|
720
|
-
return true;
|
|
584
|
+
return this._deleteNode(node);
|
|
721
585
|
}
|
|
722
586
|
/**
|
|
723
|
-
*
|
|
724
|
-
*
|
|
725
|
-
*
|
|
726
|
-
*
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
587
|
+
* Delete the first entry that matches a predicate.
|
|
588
|
+
* @remarks Time O(N), Space O(1)
|
|
589
|
+
* @param predicate - Function (key, value, index, map) → boolean to decide deletion.
|
|
590
|
+
* @returns True if an entry was removed.
|
|
591
|
+
*/
|
|
592
|
+
deleteWhere(predicate) {
|
|
593
|
+
let node = this._head;
|
|
594
|
+
let i = 0;
|
|
595
|
+
while (node !== this._sentinel) {
|
|
596
|
+
const cur = node;
|
|
597
|
+
node = node.next;
|
|
598
|
+
if (predicate(cur.key, cur.value, i++, this)) {
|
|
599
|
+
if (isWeakKey(cur.key)) {
|
|
600
|
+
this._objMap.delete(cur.key);
|
|
601
|
+
}
|
|
602
|
+
else {
|
|
603
|
+
const hash = this._hashFn(cur.key);
|
|
604
|
+
delete this._noObjMap[hash];
|
|
605
|
+
}
|
|
606
|
+
return this._deleteNode(cur);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
return false;
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Delete the entry at a given index.
|
|
613
|
+
* @remarks Time O(N), Space O(1)
|
|
614
|
+
* @param index - Zero-based index.
|
|
615
|
+
* @returns True if removed.
|
|
730
616
|
*/
|
|
731
617
|
deleteAt(index) {
|
|
732
618
|
rangeCheck(index, 0, this._size - 1);
|
|
733
619
|
let node = this.head;
|
|
734
|
-
while (index--)
|
|
620
|
+
while (index--)
|
|
735
621
|
node = node.next;
|
|
736
|
-
}
|
|
737
622
|
return this._deleteNode(node);
|
|
738
623
|
}
|
|
739
|
-
/**
|
|
740
|
-
* Time Complexity: O(1)
|
|
741
|
-
* Space Complexity: O(1)
|
|
742
|
-
*
|
|
743
|
-
* The function checks if a data structure is empty by comparing its size to zero.
|
|
744
|
-
* @returns The method is returning a boolean value indicating whether the size of the object is 0 or
|
|
745
|
-
* not.
|
|
746
|
-
*/
|
|
747
624
|
isEmpty() {
|
|
748
625
|
return this._size === 0;
|
|
749
626
|
}
|
|
750
|
-
/**
|
|
751
|
-
* The function checks if a given element is an array with exactly two elements.
|
|
752
|
-
* @param {any} rawElement - The `rawElement` parameter is of type `any`, which means it can be any
|
|
753
|
-
* data type.
|
|
754
|
-
* @returns a boolean value.
|
|
755
|
-
*/
|
|
756
627
|
isEntry(rawElement) {
|
|
757
628
|
return Array.isArray(rawElement) && rawElement.length === 2;
|
|
758
629
|
}
|
|
759
|
-
/**
|
|
760
|
-
* Time Complexity: O(1)
|
|
761
|
-
* Space Complexity: O(1)
|
|
762
|
-
*
|
|
763
|
-
* The `clear` function clears all the entries in a data structure and resets its properties.
|
|
764
|
-
*/
|
|
765
630
|
clear() {
|
|
766
631
|
this._noObjMap = {};
|
|
767
632
|
this._size = 0;
|
|
768
633
|
this._head = this._tail = this._sentinel.prev = this._sentinel.next = this._sentinel;
|
|
769
634
|
}
|
|
770
|
-
/**
|
|
771
|
-
* Time Complexity: O(n)
|
|
772
|
-
* Space Complexity: O(n)
|
|
773
|
-
*
|
|
774
|
-
* The `clone` function creates a new instance of a `LinkedHashMap` with the same key-value pairs as
|
|
775
|
-
* the original.
|
|
776
|
-
* @returns The `clone()` method is returning a new instance of `LinkedHashMap<K, V>` that is a clone
|
|
777
|
-
* of the original `LinkedHashMap` object.
|
|
778
|
-
*/
|
|
779
635
|
clone() {
|
|
780
|
-
const
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
cloned.set(key, value);
|
|
784
|
-
}
|
|
785
|
-
return cloned;
|
|
786
|
-
}
|
|
787
|
-
/**
|
|
788
|
-
* Time Complexity: O(n)
|
|
789
|
-
* Space Complexity: O(n)
|
|
790
|
-
*
|
|
791
|
-
* The `filter` function creates a new `LinkedHashMap` containing key-value pairs from the original
|
|
792
|
-
* map that satisfy a given predicate function.
|
|
793
|
-
* @param predicate - The `predicate` parameter is a callback function that takes four arguments:
|
|
794
|
-
* `value`, `key`, `index`, and `this`. It should return a boolean value indicating whether the
|
|
795
|
-
* current element should be included in the filtered map or not.
|
|
796
|
-
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
|
797
|
-
* specify the value of `this` within the `predicate` function. It is used when you want to bind a
|
|
798
|
-
* specific object as the context for the `predicate` function. If `thisArg` is not provided, `this
|
|
799
|
-
* @returns a new `LinkedHashMap` object that contains the key-value pairs from the original
|
|
800
|
-
* `LinkedHashMap` object that satisfy the given predicate function.
|
|
801
|
-
*/
|
|
636
|
+
const opts = { hashFn: this._hashFn, objHashFn: this._objHashFn };
|
|
637
|
+
return this._createLike(this, opts);
|
|
638
|
+
}
|
|
802
639
|
filter(predicate, thisArg) {
|
|
803
|
-
const
|
|
640
|
+
const out = this._createLike();
|
|
804
641
|
let index = 0;
|
|
805
642
|
for (const [key, value] of this) {
|
|
806
|
-
if (predicate.call(thisArg, key, value, index, this))
|
|
807
|
-
|
|
808
|
-
}
|
|
643
|
+
if (predicate.call(thisArg, key, value, index, this))
|
|
644
|
+
out.set(key, value);
|
|
809
645
|
index++;
|
|
810
646
|
}
|
|
811
|
-
return
|
|
812
|
-
}
|
|
813
|
-
/**
|
|
814
|
-
*
|
|
815
|
-
*
|
|
816
|
-
*
|
|
817
|
-
*
|
|
818
|
-
*
|
|
819
|
-
* @param
|
|
820
|
-
*
|
|
821
|
-
* current key-value pair, the index of the current key-value pair, and the map itself. The callback
|
|
822
|
-
* function should
|
|
823
|
-
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
|
824
|
-
* specify the value of `this` within the callback function. If provided, the callback function will
|
|
825
|
-
* be called with `thisArg` as its `this` value. If not provided, `this` will refer to the current
|
|
826
|
-
* map
|
|
827
|
-
* @returns a new `LinkedHashMap` object with the values mapped according to the provided callback
|
|
828
|
-
* function.
|
|
647
|
+
return out;
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Map each entry to a new [key, value] pair and preserve order.
|
|
651
|
+
* @remarks Time O(N), Space O(N)
|
|
652
|
+
* @template MK
|
|
653
|
+
* @template MV
|
|
654
|
+
* @param callback - Mapping function (key, value, index, map) → [newKey, newValue].
|
|
655
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
656
|
+
* @returns A new map of the same class with transformed entries.
|
|
829
657
|
*/
|
|
830
658
|
map(callback, thisArg) {
|
|
831
|
-
const
|
|
659
|
+
const out = this._createLike();
|
|
832
660
|
let index = 0;
|
|
833
661
|
for (const [key, value] of this) {
|
|
834
662
|
const [newKey, newValue] = callback.call(thisArg, key, value, index, this);
|
|
835
|
-
|
|
663
|
+
out.set(newKey, newValue);
|
|
836
664
|
index++;
|
|
837
665
|
}
|
|
838
|
-
return
|
|
666
|
+
return out;
|
|
839
667
|
}
|
|
840
|
-
/**
|
|
841
|
-
* Time Complexity: O(n)
|
|
842
|
-
* Space Complexity: O(1)
|
|
843
|
-
* where n is the number of entries in the LinkedHashMap.
|
|
844
|
-
*
|
|
845
|
-
* The above function is an iterator that yields key-value pairs from a linked list.
|
|
846
|
-
*/
|
|
847
668
|
*_getIterator() {
|
|
848
669
|
let node = this.head;
|
|
849
670
|
while (node !== this._sentinel) {
|
|
@@ -851,28 +672,20 @@ export class LinkedHashMap extends IterableEntryBase {
|
|
|
851
672
|
node = node.next;
|
|
852
673
|
}
|
|
853
674
|
}
|
|
854
|
-
/**
|
|
855
|
-
* Time Complexity: O(1)
|
|
856
|
-
* Space Complexity: O(1)
|
|
857
|
-
*
|
|
858
|
-
* The `_deleteNode` function removes a node from a doubly linked list and updates the head and tail
|
|
859
|
-
* pointers if necessary.
|
|
860
|
-
* @param node - The `node` parameter is an instance of the `HashMapLinkedNode` class, which
|
|
861
|
-
* represents a node in a linked list. It contains a key-value pair and references to the previous
|
|
862
|
-
* and next nodes in the list.
|
|
863
|
-
*/
|
|
864
675
|
_deleteNode(node) {
|
|
865
676
|
const { prev, next } = node;
|
|
866
677
|
prev.next = next;
|
|
867
678
|
next.prev = prev;
|
|
868
|
-
if (node === this.head)
|
|
679
|
+
if (node === this.head)
|
|
869
680
|
this._head = next;
|
|
870
|
-
|
|
871
|
-
if (node === this.tail) {
|
|
681
|
+
if (node === this.tail)
|
|
872
682
|
this._tail = prev;
|
|
873
|
-
}
|
|
874
683
|
this._size -= 1;
|
|
875
684
|
return true;
|
|
876
685
|
}
|
|
686
|
+
_createLike(entries = [], options) {
|
|
687
|
+
const Ctor = this.constructor;
|
|
688
|
+
return new Ctor(entries, options);
|
|
689
|
+
}
|
|
877
690
|
}
|
|
878
691
|
//# sourceMappingURL=hash-map.js.map
|