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