min-heap-typed 1.48.0 → 1.48.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data-structures/base/index.d.ts +1 -0
- package/dist/data-structures/base/index.js +17 -0
- package/dist/data-structures/base/iterable-base.d.ts +232 -0
- package/dist/data-structures/base/iterable-base.js +312 -0
- package/dist/data-structures/binary-tree/binary-tree.d.ts +45 -40
- package/dist/data-structures/binary-tree/binary-tree.js +91 -88
- package/dist/data-structures/binary-tree/tree-multimap.d.ts +12 -0
- package/dist/data-structures/binary-tree/tree-multimap.js +16 -0
- package/dist/data-structures/graph/abstract-graph.d.ts +44 -6
- package/dist/data-structures/graph/abstract-graph.js +50 -27
- package/dist/data-structures/hash/hash-map.d.ts +160 -44
- package/dist/data-structures/hash/hash-map.js +314 -82
- package/dist/data-structures/heap/heap.d.ts +50 -7
- package/dist/data-structures/heap/heap.js +60 -30
- package/dist/data-structures/index.d.ts +1 -0
- package/dist/data-structures/index.js +1 -0
- package/dist/data-structures/linked-list/doubly-linked-list.d.ts +38 -51
- package/dist/data-structures/linked-list/doubly-linked-list.js +46 -73
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +32 -51
- package/dist/data-structures/linked-list/singly-linked-list.js +40 -73
- package/dist/data-structures/queue/deque.d.ts +29 -51
- package/dist/data-structures/queue/deque.js +36 -71
- package/dist/data-structures/queue/queue.d.ts +49 -48
- package/dist/data-structures/queue/queue.js +69 -82
- package/dist/data-structures/stack/stack.d.ts +43 -10
- package/dist/data-structures/stack/stack.js +50 -31
- package/dist/data-structures/trie/trie.d.ts +41 -6
- package/dist/data-structures/trie/trie.js +53 -32
- package/dist/types/data-structures/base/base.d.ts +5 -0
- package/dist/types/data-structures/base/base.js +2 -0
- package/dist/types/data-structures/base/index.d.ts +1 -0
- package/dist/types/data-structures/base/index.js +17 -0
- package/dist/types/data-structures/hash/hash-map.d.ts +4 -0
- package/dist/types/data-structures/index.d.ts +1 -0
- package/dist/types/data-structures/index.js +1 -0
- package/package.json +2 -2
- package/src/data-structures/base/index.ts +1 -0
- package/src/data-structures/base/iterable-base.ts +329 -0
- package/src/data-structures/binary-tree/binary-tree.ts +98 -93
- package/src/data-structures/binary-tree/tree-multimap.ts +18 -0
- package/src/data-structures/graph/abstract-graph.ts +55 -28
- package/src/data-structures/hash/hash-map.ts +334 -83
- package/src/data-structures/heap/heap.ts +63 -36
- package/src/data-structures/index.ts +1 -0
- package/src/data-structures/linked-list/doubly-linked-list.ts +50 -79
- package/src/data-structures/linked-list/singly-linked-list.ts +45 -80
- package/src/data-structures/queue/deque.ts +40 -82
- package/src/data-structures/queue/queue.ts +72 -87
- package/src/data-structures/stack/stack.ts +53 -34
- package/src/data-structures/trie/trie.ts +58 -35
- package/src/types/data-structures/base/base.ts +6 -0
- package/src/types/data-structures/base/index.ts +1 -0
- package/src/types/data-structures/hash/hash-map.ts +2 -0
- package/src/types/data-structures/index.ts +1 -0
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
import { uuidV4 } from '../../utils';
|
|
9
9
|
import { PriorityQueue } from '../priority-queue';
|
|
10
10
|
import type { DijkstraResult, VertexKey } from '../../types';
|
|
11
|
+
import { PairCallback } from "../../types";
|
|
11
12
|
import { IGraph } from '../../interfaces';
|
|
12
13
|
import { Queue } from '../queue';
|
|
14
|
+
import { IterablePairBase } from "../base";
|
|
13
15
|
|
|
14
16
|
export abstract class AbstractVertex<V = any> {
|
|
15
17
|
key: VertexKey;
|
|
@@ -64,7 +66,11 @@ export abstract class AbstractGraph<
|
|
|
64
66
|
E = any,
|
|
65
67
|
VO extends AbstractVertex<V> = AbstractVertex<V>,
|
|
66
68
|
EO extends AbstractEdge<E> = AbstractEdge<E>
|
|
67
|
-
> implements IGraph<V, E, VO, EO> {
|
|
69
|
+
> extends IterablePairBase<VertexKey, V | undefined> implements IGraph<V, E, VO, EO> {
|
|
70
|
+
constructor() {
|
|
71
|
+
super();
|
|
72
|
+
}
|
|
73
|
+
|
|
68
74
|
protected _vertices: Map<VertexKey, VO> = new Map<VertexKey, VO>();
|
|
69
75
|
|
|
70
76
|
get vertices(): Map<VertexKey, VO> {
|
|
@@ -1159,50 +1165,71 @@ export abstract class AbstractGraph<
|
|
|
1159
1165
|
return this.tarjan(false, true, false, false).bridges;
|
|
1160
1166
|
}
|
|
1161
1167
|
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
forEach(callback: (entry: [VertexKey, V | undefined], index: number, map: Map<VertexKey, VO>) => void): void {
|
|
1169
|
-
let index = 0;
|
|
1170
|
-
for (const vertex of this) {
|
|
1171
|
-
callback(vertex, index, this._vertices);
|
|
1172
|
-
index++;
|
|
1173
|
-
}
|
|
1174
|
-
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Time Complexity: O(n)
|
|
1170
|
+
* Space Complexity: O(n)
|
|
1171
|
+
*/
|
|
1175
1172
|
|
|
1176
|
-
|
|
1173
|
+
/**
|
|
1174
|
+
* Time Complexity: O(n)
|
|
1175
|
+
* Space Complexity: O(n)
|
|
1176
|
+
*
|
|
1177
|
+
* The `filter` function iterates over key-value pairs in a data structure and returns an array of
|
|
1178
|
+
* pairs that satisfy a given predicate.
|
|
1179
|
+
* @param predicate - The `predicate` parameter is a callback function that takes four arguments:
|
|
1180
|
+
* `value`, `key`, `index`, and `this`. It is used to determine whether an element should be included
|
|
1181
|
+
* in the filtered array. The callback function should return `true` if the element should be
|
|
1182
|
+
* included, and `
|
|
1183
|
+
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
|
1184
|
+
* specify the value of `this` within the `predicate` function. It is used when you want to bind a
|
|
1185
|
+
* specific object as the context for the `predicate` function. If `thisArg` is provided, it will be
|
|
1186
|
+
* @returns The `filter` method returns an array of key-value pairs `[VertexKey, V | undefined][]`
|
|
1187
|
+
* that satisfy the given predicate function.
|
|
1188
|
+
*/
|
|
1189
|
+
filter(predicate: PairCallback<VertexKey, V | undefined, boolean>, thisArg?: any): [VertexKey, V | undefined][] {
|
|
1177
1190
|
const filtered: [VertexKey, V | undefined][] = [];
|
|
1178
1191
|
let index = 0;
|
|
1179
|
-
for (const
|
|
1180
|
-
if (predicate(
|
|
1181
|
-
filtered.push(
|
|
1192
|
+
for (const [key, value] of this) {
|
|
1193
|
+
if (predicate.call(thisArg, value, key, index, this)) {
|
|
1194
|
+
filtered.push([key, value]);
|
|
1182
1195
|
}
|
|
1183
1196
|
index++;
|
|
1184
1197
|
}
|
|
1185
1198
|
return filtered;
|
|
1186
1199
|
}
|
|
1187
1200
|
|
|
1188
|
-
|
|
1201
|
+
/**
|
|
1202
|
+
* Time Complexity: O(n)
|
|
1203
|
+
* Space Complexity: O(n)
|
|
1204
|
+
*/
|
|
1205
|
+
|
|
1206
|
+
/**
|
|
1207
|
+
* Time Complexity: O(n)
|
|
1208
|
+
* Space Complexity: O(n)
|
|
1209
|
+
*
|
|
1210
|
+
* The `map` function iterates over the elements of a collection and applies a callback function to
|
|
1211
|
+
* each element, returning an array of the results.
|
|
1212
|
+
* @param callback - The callback parameter is a function that will be called for each element in the
|
|
1213
|
+
* map. It takes four arguments:
|
|
1214
|
+
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
|
1215
|
+
* specify the value of `this` within the callback function. If `thisArg` is provided, it will be
|
|
1216
|
+
* used as the `this` value when calling the callback function. If `thisArg` is not provided, `
|
|
1217
|
+
* @returns The `map` function is returning an array of type `T[]`.
|
|
1218
|
+
*/
|
|
1219
|
+
map<T>(callback: PairCallback<VertexKey, V | undefined, T>, thisArg?: any): T[] {
|
|
1189
1220
|
const mapped: T[] = [];
|
|
1190
1221
|
let index = 0;
|
|
1191
|
-
for (const
|
|
1192
|
-
mapped.push(callback(
|
|
1222
|
+
for (const [key, value] of this) {
|
|
1223
|
+
mapped.push(callback.call(thisArg, value, key, index, this));
|
|
1193
1224
|
index++;
|
|
1194
1225
|
}
|
|
1195
1226
|
return mapped;
|
|
1196
1227
|
}
|
|
1197
1228
|
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
for (const entry of this) {
|
|
1202
|
-
accumulator = callback(accumulator, entry, index, this._vertices);
|
|
1203
|
-
index++;
|
|
1229
|
+
protected* _getIterator(): IterableIterator<[VertexKey, V | undefined]> {
|
|
1230
|
+
for (const vertex of this._vertices.values()) {
|
|
1231
|
+
yield [vertex.key, vertex.value];
|
|
1204
1232
|
}
|
|
1205
|
-
return accumulator;
|
|
1206
1233
|
}
|
|
1207
1234
|
|
|
1208
1235
|
protected abstract _addEdgeOnly(edge: EO): boolean;
|
|
@@ -7,9 +7,248 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { isWeakKey, rangeCheck } from '../../utils';
|
|
10
|
-
import { HashMapLinkedNode, HashMapOptions } from '../../types';
|
|
10
|
+
import { HashMapLinkedNode, HashMapOptions, HashMapStoreItem, PairCallback } from '../../types';
|
|
11
|
+
import { IterablePairBase } from "../base";
|
|
11
12
|
|
|
12
|
-
export class HashMap<K = any, V = any> {
|
|
13
|
+
export class HashMap<K = any, V = any> extends IterablePairBase<K, V> {
|
|
14
|
+
protected _store: { [key: string]: HashMapStoreItem<K, V> } = {};
|
|
15
|
+
protected _objMap: Map<object, V> = new Map();
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The constructor function initializes a new instance of a class with optional elements and options.
|
|
19
|
+
* @param elements - The `elements` parameter is an iterable containing key-value pairs `[K, V]`. It
|
|
20
|
+
* is optional and defaults to an empty array `[]`. This parameter is used to initialize the map with
|
|
21
|
+
* key-value pairs.
|
|
22
|
+
* @param [options] - The `options` parameter is an optional object that can contain additional
|
|
23
|
+
* configuration options for the constructor. In this case, it has one property:
|
|
24
|
+
*/
|
|
25
|
+
constructor(elements: Iterable<[K, V]> = [], options?: {
|
|
26
|
+
hashFn: (key: K) => string
|
|
27
|
+
}) {
|
|
28
|
+
super();
|
|
29
|
+
if (options) {
|
|
30
|
+
const { hashFn } = options;
|
|
31
|
+
if (hashFn) {
|
|
32
|
+
this._hashFn = hashFn;
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (elements) {
|
|
37
|
+
this.setMany(elements);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
protected _size = 0;
|
|
42
|
+
|
|
43
|
+
get size(): number {
|
|
44
|
+
return this._size;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
isEmpty(): boolean {
|
|
48
|
+
return this.size === 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
clear() {
|
|
52
|
+
this._store = {};
|
|
53
|
+
this._objMap.clear();
|
|
54
|
+
this._size = 0;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The `set` function adds a key-value pair to a map-like data structure, incrementing the size if
|
|
59
|
+
* the key is not already present.
|
|
60
|
+
* @param {K} key - The key parameter is the key used to identify the value in the data structure. It
|
|
61
|
+
* can be of any type, but if it is an object, it will be stored in a Map, otherwise it will be
|
|
62
|
+
* stored in a regular JavaScript object.
|
|
63
|
+
* @param {V} value - The value parameter represents the value that you want to associate with the
|
|
64
|
+
* key in the data structure.
|
|
65
|
+
*/
|
|
66
|
+
set(key: K, value: V) {
|
|
67
|
+
|
|
68
|
+
if (this._isObjKey(key)) {
|
|
69
|
+
if (!this._objMap.has(key)) {
|
|
70
|
+
this._size++;
|
|
71
|
+
}
|
|
72
|
+
this._objMap.set(key, value);
|
|
73
|
+
|
|
74
|
+
} else {
|
|
75
|
+
const strKey = this._getNoObjKey(key);
|
|
76
|
+
if (this._store[strKey] === undefined) {
|
|
77
|
+
this._size++;
|
|
78
|
+
}
|
|
79
|
+
this._store[strKey] = { key, value };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The function "setMany" sets multiple key-value pairs in a map.
|
|
85
|
+
* @param elements - The `elements` parameter is an iterable containing key-value pairs. Each
|
|
86
|
+
* key-value pair is represented as an array with two elements: the key and the value.
|
|
87
|
+
*/
|
|
88
|
+
setMany(elements: Iterable<[K, V]>) {
|
|
89
|
+
for (const [key, value] of elements) this.set(key, value);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The `get` function retrieves a value from a map based on a given key, either from an object map or
|
|
94
|
+
* a string map.
|
|
95
|
+
* @param {K} key - The `key` parameter is the key used to retrieve a value from the map. It can be
|
|
96
|
+
* of any type, but it should be compatible with the key type used when the map was created.
|
|
97
|
+
* @returns The method `get(key: K)` returns a value of type `V` if the key exists in the `_objMap`
|
|
98
|
+
* or `_store`, otherwise it returns `undefined`.
|
|
99
|
+
*/
|
|
100
|
+
get(key: K): V | undefined {
|
|
101
|
+
if (this._isObjKey(key)) {
|
|
102
|
+
return this._objMap.get(key);
|
|
103
|
+
} else {
|
|
104
|
+
const strKey = this._getNoObjKey(key);
|
|
105
|
+
return this._store[strKey]?.value;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The `has` function checks if a given key exists in the `_objMap` or `_store` based on whether it
|
|
111
|
+
* is an object key or not.
|
|
112
|
+
* @param {K} key - The parameter "key" is of type K, which means it can be any type.
|
|
113
|
+
* @returns The `has` method is returning a boolean value.
|
|
114
|
+
*/
|
|
115
|
+
has(key: K): boolean {
|
|
116
|
+
if (this._isObjKey(key)) {
|
|
117
|
+
return this._objMap.has(key);
|
|
118
|
+
} else {
|
|
119
|
+
const strKey = this._getNoObjKey(key);
|
|
120
|
+
return strKey in this._store;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* The `delete` function removes an element from a map-like data structure based on the provided key.
|
|
126
|
+
* @param {K} key - The `key` parameter is the key of the element that you want to delete from the
|
|
127
|
+
* data structure.
|
|
128
|
+
* @returns The `delete` method returns a boolean value. It returns `true` if the key was
|
|
129
|
+
* successfully deleted from the map, and `false` if the key was not found in the map.
|
|
130
|
+
*/
|
|
131
|
+
delete(key: K): boolean {
|
|
132
|
+
if (this._isObjKey(key)) {
|
|
133
|
+
if (this._objMap.has(key)) {
|
|
134
|
+
this._size--
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return this._objMap.delete(key);
|
|
138
|
+
} else {
|
|
139
|
+
const strKey = this._getNoObjKey(key);
|
|
140
|
+
if (strKey in this._store) {
|
|
141
|
+
delete this._store[strKey];
|
|
142
|
+
this._size--;
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Time Complexity: O(n)
|
|
151
|
+
* Space Complexity: O(n)
|
|
152
|
+
*/
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Time Complexity: O(n)
|
|
156
|
+
* Space Complexity: O(n)
|
|
157
|
+
*
|
|
158
|
+
* The `map` function in TypeScript creates a new HashMap by applying a callback function to each
|
|
159
|
+
* key-value pair in the original HashMap.
|
|
160
|
+
* @param callbackfn - The callback function that will be called for each key-value pair in the
|
|
161
|
+
* HashMap. It takes four parameters:
|
|
162
|
+
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
|
163
|
+
* to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will
|
|
164
|
+
* be passed as the `this` value to the `callbackfn` function. If `thisArg
|
|
165
|
+
* @returns The `map` method is returning a new `HashMap` object with the transformed values based on
|
|
166
|
+
* the provided callback function.
|
|
167
|
+
*/
|
|
168
|
+
map<U>(callbackfn: PairCallback<K, V, U>, thisArg?: any): HashMap<K, U> {
|
|
169
|
+
const resultMap = new HashMap<K, U>();
|
|
170
|
+
let index = 0;
|
|
171
|
+
for (const [key, value] of this) {
|
|
172
|
+
resultMap.set(key, callbackfn.call(thisArg, value, key, index++, this));
|
|
173
|
+
}
|
|
174
|
+
return resultMap;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Time Complexity: O(n)
|
|
179
|
+
* Space Complexity: O(n)
|
|
180
|
+
*/
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Time Complexity: O(n)
|
|
184
|
+
* Space Complexity: O(n)
|
|
185
|
+
*
|
|
186
|
+
* The `filter` function creates a new HashMap containing key-value pairs from the original HashMap
|
|
187
|
+
* that satisfy a given predicate function.
|
|
188
|
+
* @param predicate - The predicate parameter is a function that takes four arguments: value, key,
|
|
189
|
+
* index, and map. It is used to determine whether an element should be included in the filtered map
|
|
190
|
+
* or not. The function should return a boolean value - true if the element should be included, and
|
|
191
|
+
* false otherwise.
|
|
192
|
+
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
|
193
|
+
* to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be
|
|
194
|
+
* passed as the `this` value to the `predicate` function. If `thisArg` is
|
|
195
|
+
* @returns The `filter` method is returning a new `HashMap` object that contains the key-value pairs
|
|
196
|
+
* from the original `HashMap` that pass the provided `predicate` function.
|
|
197
|
+
*/
|
|
198
|
+
filter(predicate: PairCallback<K, V, boolean>, thisArg?: any): HashMap<K, V> {
|
|
199
|
+
const filteredMap = new HashMap<K, V>();
|
|
200
|
+
let index = 0;
|
|
201
|
+
for (const [key, value] of this) {
|
|
202
|
+
if (predicate.call(thisArg, value, key, index++, this)) {
|
|
203
|
+
filteredMap.set(key, value);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return filteredMap;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
print(): void {
|
|
210
|
+
console.log([...this.entries()]);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* The function returns an iterator that yields key-value pairs from both an object store and an
|
|
215
|
+
* object map.
|
|
216
|
+
*/
|
|
217
|
+
protected* _getIterator(): IterableIterator<[K, V]> {
|
|
218
|
+
for (const node of Object.values(this._store)) {
|
|
219
|
+
yield [node.key, node.value] as [K, V];
|
|
220
|
+
}
|
|
221
|
+
for (const node of this._objMap) {
|
|
222
|
+
yield node as [K, V];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
protected _hashFn: (key: K) => string = (key: K) => String(key);
|
|
227
|
+
|
|
228
|
+
protected _isObjKey(key: any): key is (object | ((...args: any[]) => any)) {
|
|
229
|
+
const keyType = typeof key;
|
|
230
|
+
return (keyType === 'object' || keyType === 'function') && key !== null
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
protected _getNoObjKey(key: K): string {
|
|
234
|
+
const keyType = typeof key;
|
|
235
|
+
|
|
236
|
+
let strKey: string;
|
|
237
|
+
if (keyType !== "string" && keyType !== "number" && keyType !== "symbol") {
|
|
238
|
+
strKey = this._hashFn(key);
|
|
239
|
+
} else {
|
|
240
|
+
if (keyType === "number") {
|
|
241
|
+
// TODO numeric key should has its own hash
|
|
242
|
+
strKey = <string>key;
|
|
243
|
+
} else {
|
|
244
|
+
strKey = <string>key;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return strKey;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export class LinkedHashMap<K = any, V = any> extends IterablePairBase<K, V> {
|
|
13
252
|
|
|
14
253
|
protected _noObjMap: Record<string, HashMapLinkedNode<K, V | undefined>> = {};
|
|
15
254
|
protected _objMap = new WeakMap<object, HashMapLinkedNode<K, V | undefined>>();
|
|
@@ -25,6 +264,7 @@ export class HashMap<K = any, V = any> {
|
|
|
25
264
|
hashFn: (key: K) => String(key),
|
|
26
265
|
objHashFn: (key: K) => (<object>key)
|
|
27
266
|
}) {
|
|
267
|
+
super();
|
|
28
268
|
this._sentinel = <HashMapLinkedNode<K, V>>{};
|
|
29
269
|
this._sentinel.prev = this._sentinel.next = this._head = this._tail = this._sentinel;
|
|
30
270
|
|
|
@@ -108,49 +348,64 @@ export class HashMap<K = any, V = any> {
|
|
|
108
348
|
*/
|
|
109
349
|
set(key: K, value?: V) {
|
|
110
350
|
let node;
|
|
351
|
+
const isNewKey = !this.has(key); // Check if the key is new
|
|
111
352
|
|
|
112
353
|
if (isWeakKey(key)) {
|
|
113
354
|
const hash = this._objHashFn(key);
|
|
114
355
|
node = this._objMap.get(hash);
|
|
115
356
|
|
|
116
|
-
if (node) {
|
|
117
|
-
// If the node already exists, update its value
|
|
118
|
-
node.value = value;
|
|
119
|
-
} else {
|
|
357
|
+
if (!node && isNewKey) {
|
|
120
358
|
// Create new node
|
|
121
359
|
node = { key: <K>hash, value, prev: this._tail, next: this._sentinel };
|
|
122
|
-
|
|
123
|
-
// Add new nodes to _objMap and linked list
|
|
124
360
|
this._objMap.set(hash, node);
|
|
361
|
+
} else if (node) {
|
|
362
|
+
// Update the value of an existing node
|
|
363
|
+
node.value = value;
|
|
125
364
|
}
|
|
126
365
|
} else {
|
|
127
366
|
const hash = this._hashFn(key);
|
|
128
|
-
// Non-object keys are handled in the same way as the original implementation
|
|
129
367
|
node = this._noObjMap[hash];
|
|
130
|
-
|
|
368
|
+
|
|
369
|
+
if (!node && isNewKey) {
|
|
370
|
+
this._noObjMap[hash] = node = { key, value, prev: this._tail, next: this._sentinel };
|
|
371
|
+
} else if (node) {
|
|
372
|
+
// Update the value of an existing node
|
|
131
373
|
node.value = value;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
if (node && isNewKey) {
|
|
378
|
+
// Update the head and tail of the linked list
|
|
379
|
+
if (this._size === 0) {
|
|
380
|
+
this._head = node;
|
|
381
|
+
this._sentinel.next = node;
|
|
132
382
|
} else {
|
|
133
|
-
this.
|
|
134
|
-
|
|
135
|
-
value,
|
|
136
|
-
prev: this._tail,
|
|
137
|
-
next: this._sentinel
|
|
138
|
-
};
|
|
383
|
+
this._tail.next = node;
|
|
384
|
+
node.prev = this._tail; // Make sure that the prev of the new node points to the current tail node
|
|
139
385
|
}
|
|
386
|
+
this._tail = node;
|
|
387
|
+
this._sentinel.prev = node;
|
|
388
|
+
this._size++;
|
|
140
389
|
}
|
|
141
390
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
391
|
+
return this._size;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
has(key: K): boolean {
|
|
395
|
+
if (isWeakKey(key)) {
|
|
396
|
+
const hash = this._objHashFn(key);
|
|
397
|
+
return this._objMap.has(hash);
|
|
145
398
|
} else {
|
|
146
|
-
|
|
399
|
+
const hash = this._hashFn(key);
|
|
400
|
+
return hash in this._noObjMap;
|
|
147
401
|
}
|
|
402
|
+
}
|
|
148
403
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
404
|
+
setMany(entries: Iterable<[K, V]>): void {
|
|
405
|
+
for (const entry of entries) {
|
|
406
|
+
const [key, value] = entry;
|
|
407
|
+
this.set(key, value);
|
|
408
|
+
}
|
|
154
409
|
}
|
|
155
410
|
|
|
156
411
|
/**
|
|
@@ -283,37 +538,40 @@ export class HashMap<K = any, V = any> {
|
|
|
283
538
|
this._head = this._tail = this._sentinel.prev = this._sentinel.next = this._sentinel;
|
|
284
539
|
}
|
|
285
540
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
* each element.
|
|
292
|
-
* @param callback - The callback parameter is a function that will be called for each element in the
|
|
293
|
-
* HashMap. It takes three arguments:
|
|
294
|
-
*/
|
|
295
|
-
forEach(callback: (element: [K, V], index: number, hashMap: HashMap<K, V>) => void) {
|
|
296
|
-
let index = 0;
|
|
297
|
-
let node = this._head;
|
|
298
|
-
while (node !== this._sentinel) {
|
|
299
|
-
callback(<[K, V]>[node.key, node.value], index++, this);
|
|
300
|
-
node = node.next;
|
|
541
|
+
clone(): LinkedHashMap<K, V> {
|
|
542
|
+
const cloned = new LinkedHashMap<K, V>([], { hashFn: this._hashFn, objHashFn: this._objHashFn });
|
|
543
|
+
for (const entry of this) {
|
|
544
|
+
const [key, value] = entry;
|
|
545
|
+
cloned.set(key, value);
|
|
301
546
|
}
|
|
547
|
+
return cloned;
|
|
302
548
|
}
|
|
303
549
|
|
|
304
550
|
/**
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
* @param predicate - The `predicate` parameter is a function that takes two arguments: `element` and
|
|
308
|
-
* `map`.
|
|
309
|
-
* @returns a new HashMap object that contains the key-value pairs from the original HashMap that
|
|
310
|
-
* satisfy the given predicate function.
|
|
551
|
+
* Time Complexity: O(n)
|
|
552
|
+
* Space Complexity: O(n)
|
|
311
553
|
*/
|
|
312
|
-
|
|
313
|
-
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Time Complexity: O(n)
|
|
557
|
+
* Space Complexity: O(n)
|
|
558
|
+
*
|
|
559
|
+
* The `filter` function creates a new `LinkedHashMap` containing key-value pairs from the original
|
|
560
|
+
* map that satisfy a given predicate function.
|
|
561
|
+
* @param predicate - The `predicate` parameter is a callback function that takes four arguments:
|
|
562
|
+
* `value`, `key`, `index`, and `this`. It should return a boolean value indicating whether the
|
|
563
|
+
* current element should be included in the filtered map or not.
|
|
564
|
+
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
|
565
|
+
* specify the value of `this` within the `predicate` function. It is used when you want to bind a
|
|
566
|
+
* specific object as the context for the `predicate` function. If `thisArg` is not provided, `this
|
|
567
|
+
* @returns a new `LinkedHashMap` object that contains the key-value pairs from the original
|
|
568
|
+
* `LinkedHashMap` object that satisfy the given predicate function.
|
|
569
|
+
*/
|
|
570
|
+
filter(predicate: PairCallback<K, V, boolean>, thisArg?: any): LinkedHashMap<K, V> {
|
|
571
|
+
const filteredMap = new LinkedHashMap<K, V>();
|
|
314
572
|
let index = 0;
|
|
315
573
|
for (const [key, value] of this) {
|
|
316
|
-
if (predicate(
|
|
574
|
+
if (predicate.call(thisArg, value, key, index, this)) {
|
|
317
575
|
filteredMap.set(key, value);
|
|
318
576
|
}
|
|
319
577
|
index++;
|
|
@@ -322,52 +580,49 @@ export class HashMap<K = any, V = any> {
|
|
|
322
580
|
}
|
|
323
581
|
|
|
324
582
|
/**
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
583
|
+
* Time Complexity: O(n)
|
|
584
|
+
* Space Complexity: O(n)
|
|
585
|
+
*/
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Time Complexity: O(n)
|
|
589
|
+
* Space Complexity: O(n)
|
|
590
|
+
*
|
|
591
|
+
* The `map` function in TypeScript creates a new `LinkedHashMap` by applying a callback function to
|
|
592
|
+
* each key-value pair in the original map.
|
|
593
|
+
* @param callback - The callback parameter is a function that will be called for each key-value pair
|
|
594
|
+
* in the map. It takes four arguments: the value of the current key-value pair, the key of the
|
|
595
|
+
* current key-value pair, the index of the current key-value pair, and the map itself. The callback
|
|
596
|
+
* function should
|
|
597
|
+
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
|
598
|
+
* specify the value of `this` within the callback function. If provided, the callback function will
|
|
599
|
+
* be called with `thisArg` as its `this` value. If not provided, `this` will refer to the current
|
|
600
|
+
* map
|
|
601
|
+
* @returns a new `LinkedHashMap` object with the values mapped according to the provided callback
|
|
602
|
+
* function.
|
|
330
603
|
*/
|
|
331
|
-
map<NV>(callback:
|
|
332
|
-
const mappedMap = new
|
|
604
|
+
map<NV>(callback: PairCallback<K, V, NV>, thisArg?: any): LinkedHashMap<K, NV> {
|
|
605
|
+
const mappedMap = new LinkedHashMap<K, NV>();
|
|
333
606
|
let index = 0;
|
|
334
607
|
for (const [key, value] of this) {
|
|
335
|
-
const newValue = callback(
|
|
608
|
+
const newValue = callback.call(thisArg, value, key, index, this);
|
|
336
609
|
mappedMap.set(key, newValue);
|
|
337
610
|
index++;
|
|
338
611
|
}
|
|
339
612
|
return mappedMap;
|
|
340
613
|
}
|
|
341
614
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
* each element, accumulating a single value.
|
|
345
|
-
* @param callback - The callback parameter is a function that takes three arguments: accumulator,
|
|
346
|
-
* element, and map. It is called for each element in the HashMap and is used to accumulate a single
|
|
347
|
-
* result.
|
|
348
|
-
* @param {A} initialValue - The `initialValue` parameter is the initial value of the accumulator. It
|
|
349
|
-
* is the value that will be passed as the first argument to the `callback` function when reducing
|
|
350
|
-
* the elements of the map.
|
|
351
|
-
* @returns The `reduce` function is returning the final value of the accumulator after iterating
|
|
352
|
-
* over all the elements in the HashMap and applying the callback function to each element.
|
|
353
|
-
*/
|
|
354
|
-
reduce<A>(callback: (accumulator: A, element: [K, V], index: number, map: HashMap<K, V>) => A, initialValue: A): A {
|
|
355
|
-
let accumulator = initialValue;
|
|
356
|
-
let index = 0;
|
|
357
|
-
for (const entry of this) {
|
|
358
|
-
accumulator = callback(accumulator, entry, index, this);
|
|
359
|
-
index++;
|
|
360
|
-
}
|
|
361
|
-
return accumulator;
|
|
615
|
+
print() {
|
|
616
|
+
console.log([...this]);
|
|
362
617
|
}
|
|
363
618
|
|
|
364
619
|
/**
|
|
365
|
-
* Time Complexity: O(n), where n is the number of elements in the
|
|
620
|
+
* Time Complexity: O(n), where n is the number of elements in the LinkedHashMap.
|
|
366
621
|
* Space Complexity: O(1)
|
|
367
622
|
*
|
|
368
623
|
* The above function is an iterator that yields key-value pairs from a linked list.
|
|
369
624
|
*/
|
|
370
|
-
*
|
|
625
|
+
protected* _getIterator() {
|
|
371
626
|
let node = this._head;
|
|
372
627
|
while (node !== this._sentinel) {
|
|
373
628
|
yield <[K, V]>[node.key, node.value];
|
|
@@ -375,10 +630,6 @@ export class HashMap<K = any, V = any> {
|
|
|
375
630
|
}
|
|
376
631
|
}
|
|
377
632
|
|
|
378
|
-
print() {
|
|
379
|
-
console.log([...this]);
|
|
380
|
-
}
|
|
381
|
-
|
|
382
633
|
/**
|
|
383
634
|
* Time Complexity: O(1)
|
|
384
635
|
* Space Complexity: O(1)
|