data-structure-typed 1.46.2 → 1.46.4
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 +1 -1
- package/README.md +16 -16
- package/benchmark/report.html +1 -46
- package/benchmark/report.json +8 -389
- package/dist/cjs/data-structures/hash/hash-map.d.ts +31 -116
- package/dist/cjs/data-structures/hash/hash-map.js +127 -254
- package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
- package/dist/cjs/data-structures/hash/index.d.ts +0 -4
- package/dist/cjs/data-structures/hash/index.js +0 -4
- package/dist/cjs/data-structures/hash/index.js.map +1 -1
- package/dist/cjs/data-structures/queue/deque.d.ts +6 -74
- package/dist/cjs/data-structures/queue/deque.js +20 -142
- package/dist/cjs/data-structures/queue/deque.js.map +1 -1
- package/dist/cjs/types/data-structures/hash/hash-map.d.ts +5 -0
- package/dist/cjs/types/data-structures/hash/index.d.ts +0 -4
- package/dist/cjs/types/data-structures/hash/index.js +0 -4
- package/dist/cjs/types/data-structures/hash/index.js.map +1 -1
- package/dist/cjs/utils/utils.d.ts +1 -1
- package/dist/cjs/utils/utils.js +3 -3
- package/dist/cjs/utils/utils.js.map +1 -1
- package/dist/mjs/data-structures/hash/hash-map.d.ts +31 -116
- package/dist/mjs/data-structures/hash/hash-map.js +129 -257
- package/dist/mjs/data-structures/hash/index.d.ts +0 -4
- package/dist/mjs/data-structures/hash/index.js +0 -4
- package/dist/mjs/data-structures/queue/deque.d.ts +6 -74
- package/dist/mjs/data-structures/queue/deque.js +16 -140
- package/dist/mjs/types/data-structures/hash/hash-map.d.ts +5 -0
- package/dist/mjs/types/data-structures/hash/index.d.ts +0 -4
- package/dist/mjs/types/data-structures/hash/index.js +0 -4
- package/dist/mjs/utils/utils.d.ts +1 -1
- package/dist/mjs/utils/utils.js +1 -1
- package/dist/umd/data-structure-typed.js +169 -531
- package/dist/umd/data-structure-typed.min.js +1 -1
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +4 -3
- package/src/data-structures/hash/hash-map.ts +154 -275
- package/src/data-structures/hash/index.ts +0 -4
- package/src/data-structures/queue/deque.ts +22 -161
- package/src/types/data-structures/hash/hash-map.ts +6 -0
- package/src/types/data-structures/hash/index.ts +0 -4
- package/src/utils/utils.ts +1 -1
- package/test/performance/data-structures/hash/hash-map.test.ts +86 -11
- package/test/performance/reportor.ts +6 -3
- package/test/unit/data-structures/hash/hash-map.test.ts +36 -5
- package/test/unit/data-structures/queue/deque.test.ts +28 -0
- package/dist/cjs/data-structures/hash/coordinate-map.d.ts +0 -44
- package/dist/cjs/data-structures/hash/coordinate-map.js +0 -63
- package/dist/cjs/data-structures/hash/coordinate-map.js.map +0 -1
- package/dist/cjs/data-structures/hash/coordinate-set.d.ts +0 -36
- package/dist/cjs/data-structures/hash/coordinate-set.js +0 -53
- package/dist/cjs/data-structures/hash/coordinate-set.js.map +0 -1
- package/dist/cjs/data-structures/hash/tree-map.d.ts +0 -2
- package/dist/cjs/data-structures/hash/tree-map.js +0 -7
- package/dist/cjs/data-structures/hash/tree-map.js.map +0 -1
- package/dist/cjs/data-structures/hash/tree-set.d.ts +0 -2
- package/dist/cjs/data-structures/hash/tree-set.js +0 -7
- package/dist/cjs/data-structures/hash/tree-set.js.map +0 -1
- package/dist/cjs/types/data-structures/hash/coordinate-map.d.ts +0 -1
- package/dist/cjs/types/data-structures/hash/coordinate-map.js +0 -3
- package/dist/cjs/types/data-structures/hash/coordinate-map.js.map +0 -1
- package/dist/cjs/types/data-structures/hash/coordinate-set.d.ts +0 -1
- package/dist/cjs/types/data-structures/hash/coordinate-set.js +0 -3
- package/dist/cjs/types/data-structures/hash/coordinate-set.js.map +0 -1
- package/dist/cjs/types/data-structures/hash/tree-map.d.ts +0 -1
- package/dist/cjs/types/data-structures/hash/tree-map.js +0 -3
- package/dist/cjs/types/data-structures/hash/tree-map.js.map +0 -1
- package/dist/cjs/types/data-structures/hash/tree-set.d.ts +0 -1
- package/dist/cjs/types/data-structures/hash/tree-set.js +0 -3
- package/dist/cjs/types/data-structures/hash/tree-set.js.map +0 -1
- package/dist/mjs/data-structures/hash/coordinate-map.d.ts +0 -44
- package/dist/mjs/data-structures/hash/coordinate-map.js +0 -58
- package/dist/mjs/data-structures/hash/coordinate-set.d.ts +0 -36
- package/dist/mjs/data-structures/hash/coordinate-set.js +0 -48
- package/dist/mjs/data-structures/hash/tree-map.d.ts +0 -2
- package/dist/mjs/data-structures/hash/tree-map.js +0 -2
- package/dist/mjs/data-structures/hash/tree-set.d.ts +0 -2
- package/dist/mjs/data-structures/hash/tree-set.js +0 -2
- package/dist/mjs/types/data-structures/hash/coordinate-map.d.ts +0 -1
- package/dist/mjs/types/data-structures/hash/coordinate-map.js +0 -1
- package/dist/mjs/types/data-structures/hash/coordinate-set.d.ts +0 -1
- package/dist/mjs/types/data-structures/hash/coordinate-set.js +0 -1
- package/dist/mjs/types/data-structures/hash/tree-map.d.ts +0 -1
- package/dist/mjs/types/data-structures/hash/tree-map.js +0 -1
- package/dist/mjs/types/data-structures/hash/tree-set.d.ts +0 -1
- package/dist/mjs/types/data-structures/hash/tree-set.js +0 -1
- package/src/data-structures/hash/coordinate-map.ts +0 -63
- package/src/data-structures/hash/coordinate-set.ts +0 -52
- package/src/data-structures/hash/tree-map.ts +0 -2
- package/src/data-structures/hash/tree-set.ts +0 -2
- package/src/types/data-structures/hash/coordinate-map.ts +0 -1
- package/src/types/data-structures/hash/coordinate-set.ts +0 -1
- package/src/types/data-structures/hash/tree-map.ts +0 -1
- package/src/types/data-structures/hash/tree-set.ts +0 -1
- package/test/performance/data-structures/hash/coordinate-map.test.ts +0 -0
- package/test/performance/data-structures/hash/coordinate-set.test.ts +0 -0
- package/test/unit/data-structures/hash/coordinate-map.test.ts +0 -74
- package/test/unit/data-structures/hash/coordinate-set.test.ts +0 -66
|
@@ -5,183 +5,40 @@
|
|
|
5
5
|
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
9
|
-
/**
|
|
10
|
-
* Because the implementation of HashMap relies on JavaScript's built-in objects and arrays,
|
|
11
|
-
* these underlying structures have already dealt with dynamic expansion and hash collisions.
|
|
12
|
-
* Therefore, there is no need for additional logic to handle these issues.
|
|
13
|
-
*/
|
|
14
|
-
export class HashMapIterator {
|
|
15
|
-
hashMap;
|
|
16
|
-
iterateDirection;
|
|
17
|
-
_node;
|
|
18
|
-
_sentinel;
|
|
19
|
-
/**
|
|
20
|
-
* This is a constructor function for a linked list iterator in a HashMap data structure.
|
|
21
|
-
* @param node - The `node` parameter is a reference to a `HashMapLinkedNode` object. This object
|
|
22
|
-
* represents a node in a linked list used in a hash map data structure. It contains a key-value pair
|
|
23
|
-
* and references to the previous and next nodes in the linked list.
|
|
24
|
-
* @param sentinel - The `sentinel` parameter is a reference to a special node in a linked list. It
|
|
25
|
-
* is used to mark the beginning or end of the list and is typically used in data structures like
|
|
26
|
-
* hash maps or linked lists to simplify operations and boundary checks.
|
|
27
|
-
* @param hashMap - A HashMap object that stores key-value pairs.
|
|
28
|
-
* @param {IterateDirection} iterateDirection - The `iterateDirection` parameter is an optional
|
|
29
|
-
* parameter that specifies the direction in which the iterator should iterate over the elements of
|
|
30
|
-
* the HashMap. It can take one of the following values:
|
|
31
|
-
* @returns The constructor does not return anything. It is used to initialize the properties and
|
|
32
|
-
* methods of the object being created.
|
|
33
|
-
*/
|
|
34
|
-
constructor(node, sentinel, hashMap, iterateDirection = 0 /* IterateDirection.DEFAULT */) {
|
|
35
|
-
this._node = node;
|
|
36
|
-
this._sentinel = sentinel;
|
|
37
|
-
this.iterateDirection = iterateDirection;
|
|
38
|
-
if (this.iterateDirection === 0 /* IterateDirection.DEFAULT */) {
|
|
39
|
-
this.prev = function () {
|
|
40
|
-
if (this._node.prev === this._sentinel) {
|
|
41
|
-
throwRangeError();
|
|
42
|
-
}
|
|
43
|
-
this._node = this._node.prev;
|
|
44
|
-
return this;
|
|
45
|
-
};
|
|
46
|
-
this.next = function () {
|
|
47
|
-
if (this._node === this._sentinel) {
|
|
48
|
-
throwRangeError();
|
|
49
|
-
}
|
|
50
|
-
this._node = this._node.next;
|
|
51
|
-
return this;
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
this.prev = function () {
|
|
56
|
-
if (this._node.next === this._sentinel) {
|
|
57
|
-
throwRangeError();
|
|
58
|
-
}
|
|
59
|
-
this._node = this._node.next;
|
|
60
|
-
return this;
|
|
61
|
-
};
|
|
62
|
-
this.next = function () {
|
|
63
|
-
if (this._node === this._sentinel) {
|
|
64
|
-
throwRangeError();
|
|
65
|
-
}
|
|
66
|
-
this._node = this._node.prev;
|
|
67
|
-
return this;
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
this.hashMap = hashMap;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* The above function returns a Proxy object that allows access to the key and value of a node in a
|
|
74
|
-
* data structure.
|
|
75
|
-
* @returns The code is returning a Proxy object.
|
|
76
|
-
*/
|
|
77
|
-
get current() {
|
|
78
|
-
if (this._node === this._sentinel) {
|
|
79
|
-
throwRangeError();
|
|
80
|
-
}
|
|
81
|
-
return new Proxy([], {
|
|
82
|
-
get: (target, prop) => {
|
|
83
|
-
if (prop === '0')
|
|
84
|
-
return this._node.key;
|
|
85
|
-
else if (prop === '1')
|
|
86
|
-
return this._node.value;
|
|
87
|
-
target[0] = this._node.key;
|
|
88
|
-
target[1] = this._node.value;
|
|
89
|
-
return target[prop];
|
|
90
|
-
},
|
|
91
|
-
set: (_, prop, newValue) => {
|
|
92
|
-
if (prop !== '1') {
|
|
93
|
-
throw new TypeError(`prop should be string '1'`);
|
|
94
|
-
}
|
|
95
|
-
this._node.value = newValue;
|
|
96
|
-
return true;
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* The function checks if a node is accessible.
|
|
102
|
-
* @returns a boolean value indicating whether the `_node` is not equal to the `_sentinel`.
|
|
103
|
-
*/
|
|
104
|
-
isAccessible() {
|
|
105
|
-
return this._node !== this._sentinel;
|
|
106
|
-
}
|
|
107
|
-
prev() {
|
|
108
|
-
return this;
|
|
109
|
-
}
|
|
110
|
-
next() {
|
|
111
|
-
return this;
|
|
112
|
-
}
|
|
113
|
-
clone() {
|
|
114
|
-
return new HashMapIterator(this._node, this._sentinel, this.hashMap, this.iterateDirection);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
8
|
+
import { isWeakKey, rangeCheck } from '../../utils';
|
|
117
9
|
export class HashMap {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
_orgMap = {};
|
|
10
|
+
_noObjMap = {};
|
|
11
|
+
_objMap = new WeakMap();
|
|
121
12
|
_head;
|
|
122
13
|
_tail;
|
|
123
14
|
_sentinel;
|
|
15
|
+
_hashFn;
|
|
16
|
+
_objHashFn;
|
|
124
17
|
/**
|
|
125
|
-
* The constructor initializes a
|
|
126
|
-
* @param
|
|
127
|
-
*
|
|
128
|
-
* `K` represents the type of the key and `V` represents the
|
|
18
|
+
* The constructor initializes a HashMapLinkedNode with an optional iterable of key-value pairs.
|
|
19
|
+
* @param options - The `options` parameter is an object that contains the `elements` property. The
|
|
20
|
+
* `elements` property is an iterable that contains key-value pairs represented as arrays `[K, V]`.
|
|
129
21
|
*/
|
|
130
|
-
constructor(
|
|
131
|
-
|
|
22
|
+
constructor(options = {
|
|
23
|
+
elements: [],
|
|
24
|
+
hashFn: (key) => String(key),
|
|
25
|
+
objHashFn: (key) => key
|
|
26
|
+
}) {
|
|
132
27
|
this._sentinel = {};
|
|
133
28
|
this._sentinel.prev = this._sentinel.next = this._head = this._tail = this._sentinel;
|
|
134
|
-
|
|
135
|
-
|
|
29
|
+
const { elements, hashFn, objHashFn } = options;
|
|
30
|
+
this._hashFn = hashFn;
|
|
31
|
+
this._objHashFn = objHashFn;
|
|
32
|
+
if (elements) {
|
|
33
|
+
for (const el of elements) {
|
|
34
|
+
this.set(el[0], el[1]);
|
|
35
|
+
}
|
|
136
36
|
}
|
|
137
37
|
}
|
|
138
38
|
_size = 0;
|
|
139
39
|
get size() {
|
|
140
40
|
return this._size;
|
|
141
41
|
}
|
|
142
|
-
/**
|
|
143
|
-
* Time Complexity: O(1)
|
|
144
|
-
* Space Complexity: O(1)
|
|
145
|
-
*
|
|
146
|
-
* The function returns a new iterator object for a HashMap.
|
|
147
|
-
* @returns A new instance of the HashMapIterator class is being returned.
|
|
148
|
-
*/
|
|
149
|
-
get begin() {
|
|
150
|
-
return new HashMapIterator(this._head, this._sentinel, this);
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Time Complexity: O(1)
|
|
154
|
-
* Space Complexity: O(1)
|
|
155
|
-
*
|
|
156
|
-
* The function returns a new HashMapIterator object with the _sentinel value as both the start and
|
|
157
|
-
* end values.
|
|
158
|
-
* @returns A new instance of the HashMapIterator class is being returned.
|
|
159
|
-
*/
|
|
160
|
-
get end() {
|
|
161
|
-
return new HashMapIterator(this._sentinel, this._sentinel, this);
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Time Complexity: O(1)
|
|
165
|
-
* Space Complexity: O(1)
|
|
166
|
-
*
|
|
167
|
-
* The reverseBegin function returns a new HashMapIterator object that iterates over the elements of
|
|
168
|
-
* a HashMap in reverse order.
|
|
169
|
-
* @returns A new instance of the HashMapIterator class is being returned.
|
|
170
|
-
*/
|
|
171
|
-
get reverseBegin() {
|
|
172
|
-
return new HashMapIterator(this._tail, this._sentinel, this, 1 /* IterateDirection.REVERSE */);
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Time Complexity: O(1)
|
|
176
|
-
* Space Complexity: O(1)
|
|
177
|
-
*
|
|
178
|
-
* The reverseEnd function returns a new HashMapIterator object that iterates over the elements of a
|
|
179
|
-
* HashMap in reverse order.
|
|
180
|
-
* @returns A new instance of the HashMapIterator class is being returned.
|
|
181
|
-
*/
|
|
182
|
-
get reverseEnd() {
|
|
183
|
-
return new HashMapIterator(this._sentinel, this._sentinel, this, 1 /* IterateDirection.REVERSE */);
|
|
184
|
-
}
|
|
185
42
|
/**
|
|
186
43
|
* Time Complexity: O(1)
|
|
187
44
|
* Space Complexity: O(1)
|
|
@@ -208,6 +65,27 @@ export class HashMap {
|
|
|
208
65
|
return;
|
|
209
66
|
return [this._tail.key, this._tail.value];
|
|
210
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* The `begin()` function in TypeScript iterates over a linked list and yields key-value pairs.
|
|
70
|
+
*/
|
|
71
|
+
*begin() {
|
|
72
|
+
let node = this._head;
|
|
73
|
+
while (node !== this._sentinel) {
|
|
74
|
+
yield [node.key, node.value];
|
|
75
|
+
node = node.next;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The function `reverseBegin()` iterates over a linked list in reverse order, yielding each node's
|
|
80
|
+
* key and value.
|
|
81
|
+
*/
|
|
82
|
+
*reverseBegin() {
|
|
83
|
+
let node = this._tail;
|
|
84
|
+
while (node !== this._sentinel) {
|
|
85
|
+
yield [node.key, node.value];
|
|
86
|
+
node = node.prev;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
211
89
|
/**
|
|
212
90
|
* Time Complexity: O(1)
|
|
213
91
|
* Space Complexity: O(1)
|
|
@@ -218,52 +96,52 @@ export class HashMap {
|
|
|
218
96
|
* type, but typically it is a string or symbol.
|
|
219
97
|
* @param {V} [value] - The `value` parameter is an optional parameter of type `V`. It represents the
|
|
220
98
|
* value associated with the key being set in the data structure.
|
|
221
|
-
* @param {boolean} isObjectKey - A boolean flag indicating whether the key is an object key or not.
|
|
222
99
|
* @returns the size of the data structure after the key-value pair has been set.
|
|
223
100
|
*/
|
|
224
|
-
set(key, value
|
|
225
|
-
let
|
|
226
|
-
if (
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
101
|
+
set(key, value) {
|
|
102
|
+
let node;
|
|
103
|
+
if (isWeakKey(key)) {
|
|
104
|
+
// const hash = this._objHashFn(key);
|
|
105
|
+
const hash = key;
|
|
106
|
+
node = this._objMap.get(hash);
|
|
107
|
+
if (node) {
|
|
108
|
+
// If the node already exists, update its value
|
|
109
|
+
node.value = value;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Create new node
|
|
113
|
+
node = { key: hash, value, prev: this._tail, next: this._sentinel };
|
|
114
|
+
// Add new nodes to _objMap and linked list
|
|
115
|
+
this._objMap.set(hash, node);
|
|
231
116
|
}
|
|
232
|
-
Object.defineProperty(key, this.OBJ_KEY_INDEX, {
|
|
233
|
-
value: this._nodes.length,
|
|
234
|
-
configurable: true
|
|
235
|
-
});
|
|
236
|
-
newTail = {
|
|
237
|
-
key: key,
|
|
238
|
-
value: value,
|
|
239
|
-
prev: this._tail,
|
|
240
|
-
next: this._sentinel
|
|
241
|
-
};
|
|
242
|
-
this._nodes.push(newTail);
|
|
243
117
|
}
|
|
244
118
|
else {
|
|
245
|
-
const
|
|
119
|
+
const hash = this._hashFn(key);
|
|
120
|
+
// Non-object keys are handled in the same way as the original implementation
|
|
121
|
+
node = this._noObjMap[hash];
|
|
246
122
|
if (node) {
|
|
247
123
|
node.value = value;
|
|
248
|
-
return this._size;
|
|
249
124
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
125
|
+
else {
|
|
126
|
+
this._noObjMap[hash] = node = {
|
|
127
|
+
key,
|
|
128
|
+
value,
|
|
129
|
+
prev: this._tail,
|
|
130
|
+
next: this._sentinel
|
|
131
|
+
};
|
|
132
|
+
}
|
|
256
133
|
}
|
|
257
134
|
if (this._size === 0) {
|
|
258
|
-
this._head =
|
|
259
|
-
this._sentinel.next =
|
|
135
|
+
this._head = node;
|
|
136
|
+
this._sentinel.next = node;
|
|
260
137
|
}
|
|
261
138
|
else {
|
|
262
|
-
this._tail.next =
|
|
139
|
+
this._tail.next = node;
|
|
263
140
|
}
|
|
264
|
-
this._tail =
|
|
265
|
-
this._sentinel.prev =
|
|
266
|
-
|
|
141
|
+
this._tail = node;
|
|
142
|
+
this._sentinel.prev = node;
|
|
143
|
+
this._size++;
|
|
144
|
+
return this._size;
|
|
267
145
|
}
|
|
268
146
|
/**
|
|
269
147
|
* Time Complexity: O(1)
|
|
@@ -273,21 +151,22 @@ export class HashMap {
|
|
|
273
151
|
* key directly or by using an index stored in the key object.
|
|
274
152
|
* @param {K} key - The `key` parameter is the key used to retrieve a value from the map. It can be
|
|
275
153
|
* of any type, but typically it is a string or symbol.
|
|
276
|
-
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates
|
|
277
|
-
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that
|
|
278
|
-
* `key` is an object key. If `isObjectKey` is `false`, it means that `key`
|
|
279
154
|
* @returns The value associated with the given key is being returned. If the key is an object key,
|
|
280
155
|
* the value is retrieved from the `_nodes` array using the index stored in the `OBJ_KEY_INDEX`
|
|
281
|
-
* property of the key. If the key is a string key, the value is retrieved from the `
|
|
156
|
+
* property of the key. If the key is a string key, the value is retrieved from the `_noObjMap` object
|
|
282
157
|
* using the key itself. If the key is not found, `undefined` is
|
|
283
158
|
*/
|
|
284
|
-
get(key
|
|
285
|
-
if (
|
|
286
|
-
const
|
|
287
|
-
|
|
159
|
+
get(key) {
|
|
160
|
+
if (isWeakKey(key)) {
|
|
161
|
+
const hash = this._objHashFn(key);
|
|
162
|
+
const node = this._objMap.get(hash);
|
|
163
|
+
return node ? node.value : undefined;
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
const hash = this._hashFn(key);
|
|
167
|
+
const node = this._noObjMap[hash];
|
|
168
|
+
return node ? node.value : undefined;
|
|
288
169
|
}
|
|
289
|
-
const node = this._orgMap[key];
|
|
290
|
-
return node ? node.value : undefined;
|
|
291
170
|
}
|
|
292
171
|
/**
|
|
293
172
|
* Time Complexity: O(n), where n is the index.
|
|
@@ -308,35 +187,6 @@ export class HashMap {
|
|
|
308
187
|
}
|
|
309
188
|
return [node.key, node.value];
|
|
310
189
|
}
|
|
311
|
-
/**
|
|
312
|
-
* Time Complexity: O(1)
|
|
313
|
-
* Space Complexity: O(1)
|
|
314
|
-
*
|
|
315
|
-
* The function `getIterator` returns a new instance of `HashMapIterator` based on the provided key
|
|
316
|
-
* and whether it is an object key or not.
|
|
317
|
-
* @param {K} key - The `key` parameter is the key used to retrieve the iterator from the HashMap. It
|
|
318
|
-
* can be of any type, depending on how the HashMap is implemented.
|
|
319
|
-
* @param {boolean} [isObjectKey] - The `isObjectKey` parameter is an optional boolean parameter that
|
|
320
|
-
* indicates whether the `key` parameter is an object key. If `isObjectKey` is `true`, it means that
|
|
321
|
-
* the `key` parameter is an object and needs to be handled differently. If `isObjectKey` is `false`
|
|
322
|
-
* @returns a new instance of the `HashMapIterator` class.
|
|
323
|
-
*/
|
|
324
|
-
getIterator(key, isObjectKey) {
|
|
325
|
-
let node;
|
|
326
|
-
if (isObjectKey) {
|
|
327
|
-
const index = key[this.OBJ_KEY_INDEX];
|
|
328
|
-
if (index === undefined) {
|
|
329
|
-
node = this._sentinel;
|
|
330
|
-
}
|
|
331
|
-
else {
|
|
332
|
-
node = this._nodes[index];
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
else {
|
|
336
|
-
node = this._orgMap[key] || this._sentinel;
|
|
337
|
-
}
|
|
338
|
-
return new HashMapIterator(node, this._sentinel, this);
|
|
339
|
-
}
|
|
340
190
|
/**
|
|
341
191
|
* Time Complexity: O(1)
|
|
342
192
|
* Space Complexity: O(1)
|
|
@@ -344,28 +194,32 @@ export class HashMap {
|
|
|
344
194
|
* The `delete` function removes a key-value pair from a map-like data structure.
|
|
345
195
|
* @param {K} key - The `key` parameter is the key that you want to delete from the data structure.
|
|
346
196
|
* It can be of any type, but typically it is a string or an object.
|
|
347
|
-
* @param {boolean} isObjectKey - The `isObjectKey` parameter is a boolean flag that indicates
|
|
348
|
-
* whether the `key` parameter is an object key or not. If `isObjectKey` is `true`, it means that the
|
|
349
|
-
* `key` parameter is an object key. If `isObjectKey` is `false`, it means that the
|
|
350
197
|
* @returns a boolean value. It returns `true` if the deletion was successful, and `false` if the key
|
|
351
198
|
* was not found.
|
|
352
199
|
*/
|
|
353
|
-
delete(key
|
|
200
|
+
delete(key) {
|
|
354
201
|
let node;
|
|
355
|
-
if (
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
202
|
+
if (isWeakKey(key)) {
|
|
203
|
+
const hash = this._objHashFn(key);
|
|
204
|
+
// Get nodes from WeakMap
|
|
205
|
+
node = this._objMap.get(hash);
|
|
206
|
+
if (!node) {
|
|
207
|
+
return false; // If the node does not exist, return false
|
|
208
|
+
}
|
|
209
|
+
// Remove nodes from WeakMap
|
|
210
|
+
this._objMap.delete(hash);
|
|
362
211
|
}
|
|
363
212
|
else {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
213
|
+
const hash = this._hashFn(key);
|
|
214
|
+
// Get nodes from noObjMap
|
|
215
|
+
node = this._noObjMap[hash];
|
|
216
|
+
if (!node) {
|
|
217
|
+
return false; // If the node does not exist, return false
|
|
218
|
+
}
|
|
219
|
+
// Remove nodes from orgMap
|
|
220
|
+
delete this._noObjMap[hash];
|
|
368
221
|
}
|
|
222
|
+
// Remove node from doubly linked list
|
|
369
223
|
this._deleteNode(node);
|
|
370
224
|
return true;
|
|
371
225
|
}
|
|
@@ -405,13 +259,7 @@ export class HashMap {
|
|
|
405
259
|
* The `clear` function clears all the elements in a data structure and resets its properties.
|
|
406
260
|
*/
|
|
407
261
|
clear() {
|
|
408
|
-
|
|
409
|
-
// this._nodes.forEach(el => {
|
|
410
|
-
// delete (<Record<symbol, number>><unknown>el.key)[OBJ_KEY_INDEX];
|
|
411
|
-
// });
|
|
412
|
-
this._nodes = [];
|
|
413
|
-
this._orgMap = {};
|
|
414
|
-
Object.setPrototypeOf(this._orgMap, null);
|
|
262
|
+
this._noObjMap = {};
|
|
415
263
|
this._size = 0;
|
|
416
264
|
this._head = this._tail = this._sentinel.prev = this._sentinel.next = this._sentinel;
|
|
417
265
|
}
|
|
@@ -432,6 +280,30 @@ export class HashMap {
|
|
|
432
280
|
node = node.next;
|
|
433
281
|
}
|
|
434
282
|
}
|
|
283
|
+
filter(predicate) {
|
|
284
|
+
const filteredMap = new HashMap();
|
|
285
|
+
for (const [key, value] of this) {
|
|
286
|
+
if (predicate([key, value], this)) {
|
|
287
|
+
filteredMap.set(key, value);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return filteredMap;
|
|
291
|
+
}
|
|
292
|
+
map(callback) {
|
|
293
|
+
const mappedMap = new HashMap();
|
|
294
|
+
for (const [key, value] of this) {
|
|
295
|
+
const newValue = callback([key, value], this);
|
|
296
|
+
mappedMap.set(key, newValue);
|
|
297
|
+
}
|
|
298
|
+
return mappedMap;
|
|
299
|
+
}
|
|
300
|
+
reduce(callback, initialValue) {
|
|
301
|
+
let accumulator = initialValue;
|
|
302
|
+
for (const element of this) {
|
|
303
|
+
accumulator = callback(accumulator, element, this);
|
|
304
|
+
}
|
|
305
|
+
return accumulator;
|
|
306
|
+
}
|
|
435
307
|
/**
|
|
436
308
|
* Time Complexity: O(n), where n is the number of elements in the HashMap.
|
|
437
309
|
* Space Complexity: O(1)
|
|
@@ -5,39 +5,13 @@
|
|
|
5
5
|
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
|
-
import { IterableWithSizeOrLength
|
|
8
|
+
import { IterableWithSizeOrLength } from "../../types";
|
|
9
9
|
/**
|
|
10
10
|
* Deque can provide random access with O(1) time complexity
|
|
11
11
|
* Deque is usually more compact and efficient in memory usage because it does not require additional space to store pointers.
|
|
12
12
|
* Deque may experience performance jitter, but DoublyLinkedList will not
|
|
13
13
|
* Deque is implemented using a dynamic array. Inserting or deleting beyond both ends of the array may require moving elements or reallocating space.
|
|
14
14
|
*/
|
|
15
|
-
export declare class DequeIterator<E> {
|
|
16
|
-
iterateDirection: IterateDirection;
|
|
17
|
-
index: number;
|
|
18
|
-
readonly deque: Deque<E>;
|
|
19
|
-
/**
|
|
20
|
-
* The constructor initializes the index, iterate direction, and prev/next functions for a
|
|
21
|
-
* DequeIterator object.
|
|
22
|
-
* @param {number} index - The index parameter represents the current index position of the iterator
|
|
23
|
-
* within the deque. It is a number that indicates the position of the element that the iterator is
|
|
24
|
-
* currently pointing to.
|
|
25
|
-
* @param deque - The `deque` parameter is an instance of the `Deque` class. It represents a
|
|
26
|
-
* double-ended queue data structure, which allows elements to be added or removed from both ends.
|
|
27
|
-
* @param iterateDirection - The `iterateDirection` parameter is an optional parameter that specifies
|
|
28
|
-
* the direction in which the iterator should iterate over the elements of the `deque`. It has a
|
|
29
|
-
* default value of `IterateDirection.DEFAULT`.
|
|
30
|
-
* @returns The constructor is not returning anything. It is used to initialize the properties of the
|
|
31
|
-
* object being created.
|
|
32
|
-
*/
|
|
33
|
-
constructor(index: number, deque: Deque<E>, iterateDirection?: IterateDirection);
|
|
34
|
-
get current(): E;
|
|
35
|
-
set current(newElement: E);
|
|
36
|
-
isAccessible(): boolean;
|
|
37
|
-
prev(): DequeIterator<E>;
|
|
38
|
-
next(): DequeIterator<E>;
|
|
39
|
-
clone(): DequeIterator<E>;
|
|
40
|
-
}
|
|
41
15
|
export declare class Deque<E> {
|
|
42
16
|
protected _bucketFirst: number;
|
|
43
17
|
protected _firstInBucket: number;
|
|
@@ -120,28 +94,14 @@ export declare class Deque<E> {
|
|
|
120
94
|
*/
|
|
121
95
|
clear(): void;
|
|
122
96
|
/**
|
|
123
|
-
* The
|
|
124
|
-
* @returns A new instance of the DequeIterator class is being returned.
|
|
125
|
-
*/
|
|
126
|
-
begin(): DequeIterator<E>;
|
|
127
|
-
/**
|
|
128
|
-
* The `end()` function returns a new `DequeIterator` object with the size and reference to the
|
|
129
|
-
* current deque.
|
|
130
|
-
* @returns A new instance of the DequeIterator class is being returned.
|
|
97
|
+
* The below function is a generator that yields elements from a collection one by one.
|
|
131
98
|
*/
|
|
132
|
-
|
|
99
|
+
begin(): Generator<E>;
|
|
133
100
|
/**
|
|
134
|
-
* The reverseBegin
|
|
135
|
-
* the
|
|
136
|
-
* @returns A new instance of the DequeIterator class is being returned.
|
|
101
|
+
* The function `reverseBegin()` is a generator that yields elements in reverse order starting from
|
|
102
|
+
* the last element.
|
|
137
103
|
*/
|
|
138
|
-
reverseBegin():
|
|
139
|
-
/**
|
|
140
|
-
* The reverseEnd() function returns a new DequeIterator object that iterates over the elements of a
|
|
141
|
-
* Deque in reverse order.
|
|
142
|
-
* @returns A new instance of the DequeIterator class is being returned.
|
|
143
|
-
*/
|
|
144
|
-
reverseEnd(): DequeIterator<E>;
|
|
104
|
+
reverseBegin(): Generator<E>;
|
|
145
105
|
/**
|
|
146
106
|
* Time Complexity - Amortized O(1) (possible reallocation)
|
|
147
107
|
* Space Complexity - O(n) (due to potential resizing).
|
|
@@ -294,34 +254,6 @@ export declare class Deque<E> {
|
|
|
294
254
|
* @returns The size of the data structure after the element has been deleted.
|
|
295
255
|
*/
|
|
296
256
|
delete(element: E): number;
|
|
297
|
-
/**
|
|
298
|
-
* Time Complexity: O(n)
|
|
299
|
-
* Space Complexity: O(1)
|
|
300
|
-
*/
|
|
301
|
-
/**
|
|
302
|
-
* Time Complexity: O(n)
|
|
303
|
-
* Space Complexity: O(1)
|
|
304
|
-
*
|
|
305
|
-
* The function deletes an element from a deque using an iterator and returns the next iterator.
|
|
306
|
-
* @param iter - The parameter `iter` is of type `DequeIterator<E>`. It represents an iterator object
|
|
307
|
-
* that is used to iterate over elements in a deque (double-ended queue).
|
|
308
|
-
* @returns the updated iterator after deleting an element from the deque.
|
|
309
|
-
*/
|
|
310
|
-
deleteByIterator(iter: DequeIterator<E>): DequeIterator<E>;
|
|
311
|
-
/**
|
|
312
|
-
* Time Complexity: O(n)
|
|
313
|
-
* Space Complexity: O(1)
|
|
314
|
-
*/
|
|
315
|
-
/**
|
|
316
|
-
* Time Complexity: O(n)
|
|
317
|
-
* Space Complexity: O(1)
|
|
318
|
-
*
|
|
319
|
-
* The function `findIterator` searches for an element in a deque and returns an iterator pointing to
|
|
320
|
-
* the element if found, otherwise it returns an iterator pointing to the end of the deque.
|
|
321
|
-
* @param {E} element - The `element` parameter is the element that you want to find in the deque.
|
|
322
|
-
* @returns The method `findIterator(element: E)` returns a `DequeIterator<E>` object.
|
|
323
|
-
*/
|
|
324
|
-
findIterator(element: E): DequeIterator<E>;
|
|
325
257
|
/**
|
|
326
258
|
* Time Complexity: O(n)
|
|
327
259
|
* Space Complexity: O(1)
|