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.
Files changed (261) hide show
  1. package/CHANGELOG.md +3 -1
  2. package/COMMANDS.md +17 -0
  3. package/README.md +11 -11
  4. package/benchmark/report.html +13 -77
  5. package/benchmark/report.json +158 -190
  6. package/dist/cjs/data-structures/base/iterable-element-base.d.ts +186 -83
  7. package/dist/cjs/data-structures/base/iterable-element-base.js +149 -107
  8. package/dist/cjs/data-structures/base/iterable-element-base.js.map +1 -1
  9. package/dist/cjs/data-structures/base/iterable-entry-base.d.ts +95 -119
  10. package/dist/cjs/data-structures/base/iterable-entry-base.js +59 -116
  11. package/dist/cjs/data-structures/base/iterable-entry-base.js.map +1 -1
  12. package/dist/cjs/data-structures/base/linear-base.d.ts +250 -192
  13. package/dist/cjs/data-structures/base/linear-base.js +137 -274
  14. package/dist/cjs/data-structures/base/linear-base.js.map +1 -1
  15. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
  16. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js +171 -205
  17. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
  18. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
  19. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +135 -87
  20. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  21. package/dist/cjs/data-structures/binary-tree/avl-tree.d.ts +138 -149
  22. package/dist/cjs/data-structures/binary-tree/avl-tree.js +208 -195
  23. package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
  24. package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +476 -632
  25. package/dist/cjs/data-structures/binary-tree/binary-tree.js +608 -875
  26. package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
  27. package/dist/cjs/data-structures/binary-tree/bst.d.ts +258 -306
  28. package/dist/cjs/data-structures/binary-tree/bst.js +505 -481
  29. package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
  30. package/dist/cjs/data-structures/binary-tree/red-black-tree.d.ts +107 -179
  31. package/dist/cjs/data-structures/binary-tree/red-black-tree.js +114 -209
  32. package/dist/cjs/data-structures/binary-tree/red-black-tree.js.map +1 -1
  33. package/dist/cjs/data-structures/binary-tree/tree-counter.d.ts +132 -154
  34. package/dist/cjs/data-structures/binary-tree/tree-counter.js +172 -203
  35. package/dist/cjs/data-structures/binary-tree/tree-counter.js.map +1 -1
  36. package/dist/cjs/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
  37. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +105 -85
  38. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  39. package/dist/cjs/data-structures/graph/abstract-graph.d.ts +238 -233
  40. package/dist/cjs/data-structures/graph/abstract-graph.js +267 -237
  41. package/dist/cjs/data-structures/graph/abstract-graph.js.map +1 -1
  42. package/dist/cjs/data-structures/graph/directed-graph.d.ts +108 -224
  43. package/dist/cjs/data-structures/graph/directed-graph.js +146 -233
  44. package/dist/cjs/data-structures/graph/directed-graph.js.map +1 -1
  45. package/dist/cjs/data-structures/graph/map-graph.d.ts +49 -55
  46. package/dist/cjs/data-structures/graph/map-graph.js +56 -59
  47. package/dist/cjs/data-structures/graph/map-graph.js.map +1 -1
  48. package/dist/cjs/data-structures/graph/undirected-graph.d.ts +103 -146
  49. package/dist/cjs/data-structures/graph/undirected-graph.js +129 -149
  50. package/dist/cjs/data-structures/graph/undirected-graph.js.map +1 -1
  51. package/dist/cjs/data-structures/hash/hash-map.d.ts +164 -338
  52. package/dist/cjs/data-structures/hash/hash-map.js +270 -457
  53. package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
  54. package/dist/cjs/data-structures/heap/heap.d.ts +214 -289
  55. package/dist/cjs/data-structures/heap/heap.js +340 -349
  56. package/dist/cjs/data-structures/heap/heap.js.map +1 -1
  57. package/dist/cjs/data-structures/heap/max-heap.d.ts +11 -47
  58. package/dist/cjs/data-structures/heap/max-heap.js +11 -66
  59. package/dist/cjs/data-structures/heap/max-heap.js.map +1 -1
  60. package/dist/cjs/data-structures/heap/min-heap.d.ts +12 -47
  61. package/dist/cjs/data-structures/heap/min-heap.js +11 -66
  62. package/dist/cjs/data-structures/heap/min-heap.js.map +1 -1
  63. package/dist/cjs/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
  64. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js +368 -494
  65. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
  66. package/dist/cjs/data-structures/linked-list/singly-linked-list.d.ts +261 -310
  67. package/dist/cjs/data-structures/linked-list/singly-linked-list.js +447 -466
  68. package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
  69. package/dist/cjs/data-structures/linked-list/skip-linked-list.d.ts +0 -107
  70. package/dist/cjs/data-structures/linked-list/skip-linked-list.js +0 -100
  71. package/dist/cjs/data-structures/linked-list/skip-linked-list.js.map +1 -1
  72. package/dist/cjs/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
  73. package/dist/cjs/data-structures/priority-queue/max-priority-queue.js +11 -78
  74. package/dist/cjs/data-structures/priority-queue/max-priority-queue.js.map +1 -1
  75. package/dist/cjs/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
  76. package/dist/cjs/data-structures/priority-queue/min-priority-queue.js +10 -79
  77. package/dist/cjs/data-structures/priority-queue/min-priority-queue.js.map +1 -1
  78. package/dist/cjs/data-structures/priority-queue/priority-queue.d.ts +2 -61
  79. package/dist/cjs/data-structures/priority-queue/priority-queue.js +8 -83
  80. package/dist/cjs/data-structures/priority-queue/priority-queue.js.map +1 -1
  81. package/dist/cjs/data-structures/queue/deque.d.ts +227 -254
  82. package/dist/cjs/data-structures/queue/deque.js +309 -348
  83. package/dist/cjs/data-structures/queue/deque.js.map +1 -1
  84. package/dist/cjs/data-structures/queue/queue.d.ts +180 -201
  85. package/dist/cjs/data-structures/queue/queue.js +265 -248
  86. package/dist/cjs/data-structures/queue/queue.js.map +1 -1
  87. package/dist/cjs/data-structures/stack/stack.d.ts +124 -102
  88. package/dist/cjs/data-structures/stack/stack.js +181 -125
  89. package/dist/cjs/data-structures/stack/stack.js.map +1 -1
  90. package/dist/cjs/data-structures/trie/trie.d.ts +164 -165
  91. package/dist/cjs/data-structures/trie/trie.js +189 -172
  92. package/dist/cjs/data-structures/trie/trie.js.map +1 -1
  93. package/dist/cjs/interfaces/binary-tree.d.ts +56 -6
  94. package/dist/cjs/interfaces/graph.d.ts +16 -0
  95. package/dist/cjs/types/data-structures/base/base.d.ts +1 -1
  96. package/dist/cjs/types/data-structures/graph/abstract-graph.d.ts +4 -0
  97. package/dist/cjs/types/utils/utils.d.ts +6 -6
  98. package/dist/cjs/utils/utils.d.ts +110 -49
  99. package/dist/cjs/utils/utils.js +148 -73
  100. package/dist/cjs/utils/utils.js.map +1 -1
  101. package/dist/esm/data-structures/base/iterable-element-base.d.ts +186 -83
  102. package/dist/esm/data-structures/base/iterable-element-base.js +155 -107
  103. package/dist/esm/data-structures/base/iterable-element-base.js.map +1 -1
  104. package/dist/esm/data-structures/base/iterable-entry-base.d.ts +95 -119
  105. package/dist/esm/data-structures/base/iterable-entry-base.js +59 -116
  106. package/dist/esm/data-structures/base/iterable-entry-base.js.map +1 -1
  107. package/dist/esm/data-structures/base/linear-base.d.ts +250 -192
  108. package/dist/esm/data-structures/base/linear-base.js +137 -274
  109. package/dist/esm/data-structures/base/linear-base.js.map +1 -1
  110. package/dist/esm/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
  111. package/dist/esm/data-structures/binary-tree/avl-tree-counter.js +171 -212
  112. package/dist/esm/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
  113. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
  114. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js +133 -94
  115. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  116. package/dist/esm/data-structures/binary-tree/avl-tree.d.ts +138 -149
  117. package/dist/esm/data-structures/binary-tree/avl-tree.js +206 -200
  118. package/dist/esm/data-structures/binary-tree/avl-tree.js.map +1 -1
  119. package/dist/esm/data-structures/binary-tree/binary-tree.d.ts +476 -632
  120. package/dist/esm/data-structures/binary-tree/binary-tree.js +613 -885
  121. package/dist/esm/data-structures/binary-tree/binary-tree.js.map +1 -1
  122. package/dist/esm/data-structures/binary-tree/bst.d.ts +258 -306
  123. package/dist/esm/data-structures/binary-tree/bst.js +507 -487
  124. package/dist/esm/data-structures/binary-tree/bst.js.map +1 -1
  125. package/dist/esm/data-structures/binary-tree/red-black-tree.d.ts +107 -179
  126. package/dist/esm/data-structures/binary-tree/red-black-tree.js +114 -215
  127. package/dist/esm/data-structures/binary-tree/red-black-tree.js.map +1 -1
  128. package/dist/esm/data-structures/binary-tree/tree-counter.d.ts +132 -154
  129. package/dist/esm/data-structures/binary-tree/tree-counter.js +175 -209
  130. package/dist/esm/data-structures/binary-tree/tree-counter.js.map +1 -1
  131. package/dist/esm/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
  132. package/dist/esm/data-structures/binary-tree/tree-multi-map.js +103 -92
  133. package/dist/esm/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  134. package/dist/esm/data-structures/graph/abstract-graph.d.ts +238 -233
  135. package/dist/esm/data-structures/graph/abstract-graph.js +267 -237
  136. package/dist/esm/data-structures/graph/abstract-graph.js.map +1 -1
  137. package/dist/esm/data-structures/graph/directed-graph.d.ts +108 -224
  138. package/dist/esm/data-structures/graph/directed-graph.js +145 -233
  139. package/dist/esm/data-structures/graph/directed-graph.js.map +1 -1
  140. package/dist/esm/data-structures/graph/map-graph.d.ts +49 -55
  141. package/dist/esm/data-structures/graph/map-graph.js +56 -59
  142. package/dist/esm/data-structures/graph/map-graph.js.map +1 -1
  143. package/dist/esm/data-structures/graph/undirected-graph.d.ts +103 -146
  144. package/dist/esm/data-structures/graph/undirected-graph.js +128 -149
  145. package/dist/esm/data-structures/graph/undirected-graph.js.map +1 -1
  146. package/dist/esm/data-structures/hash/hash-map.d.ts +164 -338
  147. package/dist/esm/data-structures/hash/hash-map.js +270 -457
  148. package/dist/esm/data-structures/hash/hash-map.js.map +1 -1
  149. package/dist/esm/data-structures/heap/heap.d.ts +214 -289
  150. package/dist/esm/data-structures/heap/heap.js +329 -349
  151. package/dist/esm/data-structures/heap/heap.js.map +1 -1
  152. package/dist/esm/data-structures/heap/max-heap.d.ts +11 -47
  153. package/dist/esm/data-structures/heap/max-heap.js +11 -66
  154. package/dist/esm/data-structures/heap/max-heap.js.map +1 -1
  155. package/dist/esm/data-structures/heap/min-heap.d.ts +12 -47
  156. package/dist/esm/data-structures/heap/min-heap.js +11 -66
  157. package/dist/esm/data-structures/heap/min-heap.js.map +1 -1
  158. package/dist/esm/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
  159. package/dist/esm/data-structures/linked-list/doubly-linked-list.js +368 -495
  160. package/dist/esm/data-structures/linked-list/doubly-linked-list.js.map +1 -1
  161. package/dist/esm/data-structures/linked-list/singly-linked-list.d.ts +261 -310
  162. package/dist/esm/data-structures/linked-list/singly-linked-list.js +448 -467
  163. package/dist/esm/data-structures/linked-list/singly-linked-list.js.map +1 -1
  164. package/dist/esm/data-structures/linked-list/skip-linked-list.d.ts +0 -107
  165. package/dist/esm/data-structures/linked-list/skip-linked-list.js +0 -100
  166. package/dist/esm/data-structures/linked-list/skip-linked-list.js.map +1 -1
  167. package/dist/esm/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
  168. package/dist/esm/data-structures/priority-queue/max-priority-queue.js +11 -78
  169. package/dist/esm/data-structures/priority-queue/max-priority-queue.js.map +1 -1
  170. package/dist/esm/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
  171. package/dist/esm/data-structures/priority-queue/min-priority-queue.js +10 -79
  172. package/dist/esm/data-structures/priority-queue/min-priority-queue.js.map +1 -1
  173. package/dist/esm/data-structures/priority-queue/priority-queue.d.ts +2 -61
  174. package/dist/esm/data-structures/priority-queue/priority-queue.js +8 -83
  175. package/dist/esm/data-structures/priority-queue/priority-queue.js.map +1 -1
  176. package/dist/esm/data-structures/queue/deque.d.ts +227 -254
  177. package/dist/esm/data-structures/queue/deque.js +313 -348
  178. package/dist/esm/data-structures/queue/deque.js.map +1 -1
  179. package/dist/esm/data-structures/queue/queue.d.ts +180 -201
  180. package/dist/esm/data-structures/queue/queue.js +263 -248
  181. package/dist/esm/data-structures/queue/queue.js.map +1 -1
  182. package/dist/esm/data-structures/stack/stack.d.ts +124 -102
  183. package/dist/esm/data-structures/stack/stack.js +181 -125
  184. package/dist/esm/data-structures/stack/stack.js.map +1 -1
  185. package/dist/esm/data-structures/trie/trie.d.ts +164 -165
  186. package/dist/esm/data-structures/trie/trie.js +193 -172
  187. package/dist/esm/data-structures/trie/trie.js.map +1 -1
  188. package/dist/esm/interfaces/binary-tree.d.ts +56 -6
  189. package/dist/esm/interfaces/graph.d.ts +16 -0
  190. package/dist/esm/types/data-structures/base/base.d.ts +1 -1
  191. package/dist/esm/types/data-structures/graph/abstract-graph.d.ts +4 -0
  192. package/dist/esm/types/utils/utils.d.ts +6 -6
  193. package/dist/esm/utils/utils.d.ts +110 -49
  194. package/dist/esm/utils/utils.js +139 -68
  195. package/dist/esm/utils/utils.js.map +1 -1
  196. package/dist/umd/data-structure-typed.js +4737 -6525
  197. package/dist/umd/data-structure-typed.min.js +8 -6
  198. package/dist/umd/data-structure-typed.min.js.map +1 -1
  199. package/package.json +3 -4
  200. package/src/data-structures/base/iterable-element-base.ts +238 -115
  201. package/src/data-structures/base/iterable-entry-base.ts +96 -120
  202. package/src/data-structures/base/linear-base.ts +271 -277
  203. package/src/data-structures/binary-tree/avl-tree-counter.ts +198 -216
  204. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +192 -101
  205. package/src/data-structures/binary-tree/avl-tree.ts +239 -206
  206. package/src/data-structures/binary-tree/binary-tree.ts +677 -901
  207. package/src/data-structures/binary-tree/bst.ts +568 -570
  208. package/src/data-structures/binary-tree/red-black-tree.ts +161 -222
  209. package/src/data-structures/binary-tree/tree-counter.ts +199 -218
  210. package/src/data-structures/binary-tree/tree-multi-map.ts +131 -97
  211. package/src/data-structures/graph/abstract-graph.ts +339 -264
  212. package/src/data-structures/graph/directed-graph.ts +146 -236
  213. package/src/data-structures/graph/map-graph.ts +63 -60
  214. package/src/data-structures/graph/undirected-graph.ts +129 -152
  215. package/src/data-structures/hash/hash-map.ts +274 -496
  216. package/src/data-structures/heap/heap.ts +389 -402
  217. package/src/data-structures/heap/max-heap.ts +12 -76
  218. package/src/data-structures/heap/min-heap.ts +13 -76
  219. package/src/data-structures/linked-list/doubly-linked-list.ts +426 -530
  220. package/src/data-structures/linked-list/singly-linked-list.ts +495 -517
  221. package/src/data-structures/linked-list/skip-linked-list.ts +1 -108
  222. package/src/data-structures/priority-queue/max-priority-queue.ts +12 -87
  223. package/src/data-structures/priority-queue/min-priority-queue.ts +11 -88
  224. package/src/data-structures/priority-queue/priority-queue.ts +3 -92
  225. package/src/data-structures/queue/deque.ts +381 -357
  226. package/src/data-structures/queue/queue.ts +310 -264
  227. package/src/data-structures/stack/stack.ts +217 -131
  228. package/src/data-structures/trie/trie.ts +240 -175
  229. package/src/interfaces/binary-tree.ts +240 -6
  230. package/src/interfaces/graph.ts +37 -0
  231. package/src/types/data-structures/base/base.ts +5 -5
  232. package/src/types/data-structures/graph/abstract-graph.ts +5 -0
  233. package/src/types/utils/utils.ts +9 -5
  234. package/src/utils/utils.ts +152 -86
  235. package/test/integration/index.html +1 -1
  236. package/test/performance/benchmark-runner.ts +528 -0
  237. package/test/performance/reportor.mjs +43 -43
  238. package/test/performance/runner-config.json +39 -0
  239. package/test/performance/single-suite-runner.ts +69 -0
  240. package/test/unit/data-structures/binary-tree/avl-tree-counter.test.ts +3 -3
  241. package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +5 -5
  242. package/test/unit/data-structures/binary-tree/avl-tree.test.ts +4 -4
  243. package/test/unit/data-structures/binary-tree/binary-tree.test.ts +350 -90
  244. package/test/unit/data-structures/binary-tree/bst.test.ts +84 -5
  245. package/test/unit/data-structures/binary-tree/red-black-tree.test.ts +2 -2
  246. package/test/unit/data-structures/binary-tree/tree-counter.test.ts +25 -24
  247. package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +3 -3
  248. package/test/unit/data-structures/graph/abstract-graph.test.ts +0 -4
  249. package/test/unit/data-structures/graph/directed-graph.test.ts +1 -1
  250. package/test/unit/data-structures/heap/heap.test.ts +14 -21
  251. package/test/unit/data-structures/heap/max-heap.test.ts +5 -9
  252. package/test/unit/data-structures/heap/min-heap.test.ts +1 -4
  253. package/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +14 -14
  254. package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +0 -7
  255. package/test/unit/data-structures/priority-queue/max-priority-queue.test.ts +8 -11
  256. package/test/unit/data-structures/priority-queue/min-priority-queue.test.ts +1 -4
  257. package/test/unit/data-structures/priority-queue/priority-queue.test.ts +1 -4
  258. package/test/unit/data-structures/queue/queue.test.ts +4 -5
  259. package/test/unit/utils/utils.test.ts +0 -1
  260. package/test/performance/data-structures/binary-tree/avl-tree.test.mjs +0 -71
  261. 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
- * The constructor function initializes a HashMap object with an optional initial collection and
59
- * options.
60
- * @param entryOrRawElements - The `entryOrRawElements` parameter is an iterable collection of elements of a type
61
- * `T`. It is an optional parameter and its default value is an empty array `[]`.
62
- * @param [options] - The `options` parameter is an optional object that can contain two properties:
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
- * The function returns the store object, which is a dictionary of HashMapStoreItem objects.
80
- * @returns The store property is being returned. It is a dictionary-like object with string keys and
81
- * values of type HashMapStoreItem<K, V>.
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
- * The function returns the object map.
89
- * @returns The `objMap` property is being returned, which is a `Map` object with keys of type
90
- * `object` and values of type `V`.
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
- * The function returns the value of the _toEntryFn property.
98
- * @returns The function being returned is `this._toEntryFn`.
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
- * The function returns the size of an object.
106
- * @returns The size of the object, which is a number.
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
- * The hasFn function is a function that takes in an item and returns a boolean
114
- * indicating whether the item is contained within the hash table.
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
- * Time Complexity: O(1)
123
- * Space Complexity: O(1)
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
- * Time Complexity: O(1)
145
- * Space Complexity: O(1)
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
- * Time Complexity: O(1)
157
- * Space Complexity: O(1)
158
- *
159
- * The `set` function adds a key-value pair to a map-like data structure, incrementing the size if
160
- * the key is not already present.
161
- * @param {K} key - The key parameter is the key used to identify the value in the data structure. It
162
- * can be of any type, but if it is an object, it will be stored in a Map, otherwise it will be
163
- * stored in a regular JavaScript object.
164
- * @param {V} value - The value parameter represents the value that you want to associate with the
165
- * key in the data structure.
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
- * Time Complexity: O(k)
185
- * Space Complexity: O(k)
186
- *
187
- * The function `setMany` takes an iterable collection of objects, maps each object to a key-value
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[0];
199
- value = rawEle[1];
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
- * Time Complexity: O(1)
213
- * Space Complexity: O(1)
214
- *
215
- * The `get` function retrieves a value from a map based on a given key, either from an object map or
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
- else {
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
- * Time Complexity: O(1)
233
- * Space Complexity: O(1)
234
- *
235
- * The `has` function checks if a given key exists in the `_objMap` or `_store` based on whether it
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
- else {
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
- * Time Complexity: O(1)
251
- * Space Complexity: O(1)
252
- *
253
- * The `delete` function removes an element from a map-like data structure based on the provided key.
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
- else {
267
- const strKey = this._getNoObjKey(key);
268
- if (strKey in this.store) {
269
- delete this.store[strKey];
270
- this._size--;
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
- * Time Complexity: O(n)
278
- * Space Complexity: O(n)
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
- return new HashMap(this, { hashFn: this._hashFn, toEntryFn: this._toEntryFn });
288
- }
289
- /**
290
- * Time Complexity: O(n)
291
- * Space Complexity: O(n)
292
- *
293
- * The `map` function in TypeScript creates a new HashMap by applying a callback function to each
294
- * key-value pair in the original HashMap.
295
- * @param callbackfn - The callback function that will be called for each key-value pair in the
296
- * HashMap. It takes four parameters:
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 resultMap = new HashMap();
274
+ const out = this._createLike();
305
275
  let index = 0;
306
- for (const [key, value] of this) {
307
- resultMap.set(key, callbackfn.call(thisArg, key, value, index++, this));
308
- }
309
- return resultMap;
310
- }
311
- /**
312
- * Time Complexity: O(n)
313
- * Space Complexity: O(n)
314
- *
315
- * The `filter` function creates a new HashMap containing key-value pairs from the original HashMap
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 filteredMap = new HashMap();
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
- filteredMap.set(key, value);
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
- * The function returns an iterator that yields key-value pairs from both an object store and an
339
- * object map.
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
- * 1. Maintaining the Order of Element Insertion: Unlike HashMap, LinkedHashMap maintains the order in which entries are inserted. Therefore, when you traverse it, entries will be returned in the order they were inserted into the map.
385
- * 2. Based on Hash Table and Linked List: It combines the structures of a hash table and a linked list, using the hash table to ensure fast access, while maintaining the order of entries through the linked list.
386
- * 3. Time Complexity: Similar to HashMap, LinkedHashMap offers constant-time performance for get and put operations in most cases.
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
- * The constructor initializes a LinkedHashMap object with an optional raw collection and options.
392
- * @param entryOrRawElements - The `entryOrRawElements` parameter is an iterable collection of elements. It is
393
- * used to initialize the HashMapLinked instance with key-value pairs. Each element in the
394
- * `entryOrRawElements` is converted to a key-value pair using the `toEntryFn` function (if provided) and
395
- * then added to the HashMap
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
- * The function returns the object hash function.
428
- * @returns The function `objHashFn` is being returned.
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
- * The function returns a record of HashMapLinkedNode objects with string keys.
436
- * @returns The method is returning a Record object, which is a TypeScript type that represents an
437
- * object with string keys and values that are HashMapLinkedNode objects with keys of type K and
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
- * The function returns the head node of a HashMapLinkedNode.
454
- * @returns The method `getHead()` is returning a `HashMapLinkedNode` object with key type `K` and
455
- * a value type `V | undefined`.
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
- * The function returns the tail node of a HashMapLinkedNode.
463
- * @returns The `_tail` property of type `HashMapLinkedNode<K, V | undefined>` is being returned.
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
- else {
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
- * Time Complexity: O(1)
494
- * Space Complexity: O(1)
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
- * Time Complexity: O(1)
507
- * Space Complexity: O(1)
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
- * The `begin()` function in TypeScript iterates over a linked list and yields key-value pairs.
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
- * The function `reverseBegin()` iterates over a linked list in reverse order, yielding each node's
530
- * key and value.
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
- * Time Complexity: O(1)
541
- * Space Complexity: O(1)
542
- *
543
- * The `set` function adds a new key-value pair to a data structure, either using an object key or a
544
- * string key.
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); // Check if the key is new
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; // Make sure that the prev of the new node points to the current tail node
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[0];
611
- value = rawEle[1];
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
- else {
638
- const hash = this._hashFn(key);
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
- else {
662
- const hash = this._hashFn(key);
663
- const node = this.noObjMap[hash];
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
- * Time Complexity: O(n)
669
- * Space Complexity: O(1)
670
- *
671
- * The function `at` retrieves the key-value pair at a specified index in a linked list.
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; // If the node does not exist, 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; // If the node does not exist, return false
714
- }
715
- // Remove nodes from orgMap
580
+ if (!node)
581
+ return false;
716
582
  delete this.noObjMap[hash];
717
583
  }
718
- // Remove node from doubly linked list
719
- this._deleteNode(node);
720
- return true;
584
+ return this._deleteNode(node);
721
585
  }
722
586
  /**
723
- * Time Complexity: O(n)
724
- * Space Complexity: O(1)
725
- *
726
- * The `deleteAt` function deletes a node at a specified index in a linked list.
727
- * @param {number} index - The index parameter represents the position at which the node should be
728
- * deleted in the linked list.
729
- * @returns The size of the list after deleting the element at the specified index.
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 cloned = new LinkedHashMap([], { hashFn: this._hashFn, objHashFn: this._objHashFn });
781
- for (const entry of this) {
782
- const [key, value] = entry;
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 filteredMap = new LinkedHashMap();
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
- filteredMap.set(key, value);
808
- }
643
+ if (predicate.call(thisArg, key, value, index, this))
644
+ out.set(key, value);
809
645
  index++;
810
646
  }
811
- return filteredMap;
812
- }
813
- /**
814
- * Time Complexity: O(n)
815
- * Space Complexity: O(n)
816
- *
817
- * The `map` function in TypeScript creates a new `LinkedHashMap` by applying a callback function to
818
- * each key-value pair in the original map.
819
- * @param callback - The callback parameter is a function that will be called for each key-value pair
820
- * in the map. It takes four arguments: the value of the current key-value pair, the key of the
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 mappedMap = new LinkedHashMap();
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
- mappedMap.set(newKey, newValue);
663
+ out.set(newKey, newValue);
836
664
  index++;
837
665
  }
838
- return mappedMap;
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