@geraintguan/ts-std-lib 1.0.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.
@@ -0,0 +1,321 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ import { identity } from "../identity.mjs";
5
+ import { HashMap } from "./HashMap.mjs";
6
+ class DefaultMap extends HashMap {
7
+ constructor(defaultValue, hash, map = /* @__PURE__ */ new Map(), name = "unknown") {
8
+ super(hash, map, name);
9
+ /**
10
+ * Default value to use in this map when accessing keys that do not exist.
11
+ *
12
+ * @remarks
13
+ *
14
+ * Two types of default value are supported:
15
+ *
16
+ * 1. Providing a **function** will make the map call the given function that
17
+ * is called with the current access key to generate the default value.
18
+ *
19
+ * 2. Providing a static **value** that will be used as-is as the default
20
+ * value.
21
+ */
22
+ __publicField(this, "defaultValue");
23
+ this.defaultValue = defaultValue;
24
+ }
25
+ /**
26
+ * Create a new empty map instance.
27
+ *
28
+ * @remarks
29
+ *
30
+ * This function uses the {@link identity} function as the hashing function
31
+ * meaning that keys will be stored without any changes.
32
+ *
33
+ * @see {@link DefaultMap.emptyWithCustomHash}
34
+ *
35
+ * @param options - Options to use to create the new map instance.
36
+ *
37
+ * @returns A new empty map instance.
38
+ */
39
+ static empty(options) {
40
+ return new DefaultMap(
41
+ options.defaultValue,
42
+ identity,
43
+ /* @__PURE__ */ new Map(),
44
+ options.name
45
+ );
46
+ }
47
+ /**
48
+ * Create a new empty mao instance with a custom hashing function.
49
+ *
50
+ * @param options - Options to use to create the new map instance.
51
+ *
52
+ * @returns A new empty map instance.
53
+ */
54
+ static emptyWithCustomHash(options) {
55
+ return new DefaultMap(
56
+ options.defaultValue,
57
+ options.hash,
58
+ /* @__PURE__ */ new Map(),
59
+ options.name
60
+ );
61
+ }
62
+ /**
63
+ * Create a new map instance from an array of key-value pairs with a custom
64
+ * hashing function.
65
+ *
66
+ * @param entries - Array of key-value pairs to create the map
67
+ * with.
68
+ * @param options - Options to use to create the new map instance.
69
+ *
70
+ * @returns A new map instance with the given key-value pairs and a given
71
+ * custom hashing function.
72
+ */
73
+ static fromCustomEntries(entries, options) {
74
+ return new DefaultMap(
75
+ options.defaultValue,
76
+ options.hash,
77
+ new Map(entries.map(([k, v]) => [options.hash(k), v])),
78
+ options.name
79
+ );
80
+ }
81
+ /**
82
+ * Create a new map instance from an array of key-value pairs
83
+ * using the {@link identity} as the hash function.
84
+ *
85
+ * @remarks
86
+ *
87
+ * This function uses the {@link identity} function as the hashing function
88
+ * meaning that keys will be stored without any changes.
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * const map = DefaultMap.fromEntries<number, string>([
93
+ * [1, "one"],
94
+ * [2, "two"],
95
+ * [3, "three"],
96
+ * ]);
97
+ *
98
+ * [...map];
99
+ * // => [
100
+ * // [1, "one"],
101
+ * // [2, "two"],
102
+ * // [3, "three"],
103
+ * // ];
104
+ * ```
105
+ *
106
+ * @param entries - Array of key-value pairs to create the map
107
+ * with.
108
+ * @param options - Options to use to create the new {map
109
+ * instance.
110
+ *
111
+ * @returns A new map instance with the given key-value pairs
112
+ * and default value.
113
+ */
114
+ static fromEntries(entries, options) {
115
+ return new DefaultMap(
116
+ options.defaultValue,
117
+ identity,
118
+ new Map(entries.map(([key, value]) => [key, value])),
119
+ options.name
120
+ );
121
+ }
122
+ /**
123
+ * Returns a new map with only the key-value pairs where the given function
124
+ * returns `true`, filtering out those that the given function returns `false`
125
+ * for.
126
+ *
127
+ * @remarks
128
+ *
129
+ * The new map will have the same default value as this map.
130
+ *
131
+ * This function does not mutate the original map instance **unless** you call
132
+ * a mutating function on the map (4th argument) inside the given function.
133
+ *
134
+ * @example Include entries where key is greater than 2
135
+ * ```typescript
136
+ * const map = HashMap.fromEntries<number, string>([
137
+ * [1, "one"],
138
+ * [2, "two"],
139
+ * [3, "three"],
140
+ * [4, "four"],
141
+ * ], {
142
+ * defaultValue: {
143
+ * type: "value",
144
+ * value: "NaN",
145
+ * }
146
+ * });
147
+ *
148
+ * const filtered = map.filter((value, key) => key > 2);
149
+ *
150
+ * [...filtered];
151
+ * // => [
152
+ * // [3, "three"],
153
+ * // [4, "four"],
154
+ * // ]
155
+ * ```
156
+ * @example Include entries where the value has a length greater than 3
157
+ * ```typescript
158
+ * const map = DefaultMap.fromEntries<number, string>([
159
+ * [1, "one"],
160
+ * [2, "two"],
161
+ * [3, "three"],
162
+ * [4, "four"],
163
+ * ], {
164
+ * defaultValue: {
165
+ * type: "value",
166
+ * value: "NaN",
167
+ * }
168
+ * });
169
+ *
170
+ * const filtered = map.filter((value) => value.length > 3);
171
+ *
172
+ * [...filtered];
173
+ * // => [
174
+ * // [3, "three"],
175
+ * // [4, "four"],
176
+ * // ]
177
+ * ```
178
+ *
179
+ * @param fn - Function called for each key-value pair in the map that returns
180
+ * `true` to include the pair in the new map or `false` to exclude it.
181
+ *
182
+ * @returns A new map with only the key-value pairs where the given function
183
+ * returned `true` for.
184
+ */
185
+ filter(fn) {
186
+ const entries = [];
187
+ for (const [key, value] of this.entries()) {
188
+ if (fn(value, key, entries.length, this)) {
189
+ entries.push([key, value]);
190
+ }
191
+ }
192
+ return new DefaultMap(
193
+ this.defaultValue,
194
+ this.hash,
195
+ new Map(entries),
196
+ this.name
197
+ );
198
+ }
199
+ /**
200
+ * Get the value with the given key from this map if it exists, if it doesn't
201
+ * return the default value configured for this map.
202
+ *
203
+ * @remarks
204
+ *
205
+ * Unlike {@link HashMap.get}, this method will not throw an error if the key
206
+ * does not exist in the map, instead returning the configured default value.
207
+ *
208
+ * Accessing an entry that does not exist with a key will set a new entry on
209
+ * the map with the given key and the created default value as the value of
210
+ * that entry.
211
+ *
212
+ * @param key - The key of the value to get.
213
+ *
214
+ * @returns The value with the given key in this map if it exists, if it
215
+ * doesn't then the default value configured for this map.
216
+ */
217
+ get(key) {
218
+ if (!this.has(key)) {
219
+ const defaultValue = this.defaultValue.type === "function" ? this.defaultValue.value(key) : this.defaultValue.value;
220
+ this.set(key, defaultValue);
221
+ return defaultValue;
222
+ }
223
+ return super.get(key);
224
+ }
225
+ /**
226
+ * Create a new map with entries that are the result of calling the given
227
+ * callback function on each of the key-value pairs in this map.
228
+ *
229
+ * @remarks
230
+ *
231
+ * The new map will have the same default value as this map.
232
+ *
233
+ * This function does not mutate the original map instance **unless** you call
234
+ * a mutating function on the map (4th argument) inside the given function.
235
+ *
236
+ * @example Swap the keys and values
237
+ * ```typescript
238
+ * const map = HashMap.fromEntries([
239
+ * ["one", 1],
240
+ * ["two", 2],
241
+ * ["three", 3],
242
+ * ], {
243
+ * defaultValue: {
244
+ * type: "value",
245
+ * value: "NaN",
246
+ * }
247
+ * });
248
+ *
249
+ * const swapped = map.map(([key, value]) => [value, key]);
250
+ * // => DefaultMap { 1 => "one", 2 => "two", 3 => "three" }
251
+ * ```
252
+ *
253
+ * @param fn - Function to call on each key-value pair in the map. The result
254
+ * of this function is used as entries in the new map.
255
+ *
256
+ * @returns A new map with the new entries from calling the given function on
257
+ * each key-value pair in the map.
258
+ */
259
+ map(fn) {
260
+ const entries = [];
261
+ for (const [key, value] of this.entries()) {
262
+ entries.push(fn(value, key, entries.length, this));
263
+ }
264
+ return new DefaultMap(
265
+ this.defaultValue,
266
+ this.hash,
267
+ new Map(entries),
268
+ this.name
269
+ );
270
+ }
271
+ /**
272
+ * Create a new map with entries that have keys that are the result of calling
273
+ * the given callback function on each of the key-value pairs in this map.
274
+ *
275
+ * @remarks
276
+ *
277
+ * The new map will have the same default value as this map.
278
+ *
279
+ * This function does not mutate the original map instance **unless** you call
280
+ * a mutating function on the map (4th argument) inside the given function.
281
+ *
282
+ * @param fn - Function to call on each key-value pair in the map. The result
283
+ * of this function is used as the keys for the entries in the new map.
284
+ *
285
+ * @returns A new map with the entries with new keys from calling the given
286
+ * function on each key-value pair in the map.
287
+ */
288
+ mapKeys(fn) {
289
+ return this.map((value, key, index, original) => [
290
+ fn(key, value, index, original),
291
+ value
292
+ ]);
293
+ }
294
+ /**
295
+ * Create a new map with entries that have values that are the result of
296
+ * calling the given callback function on each of the key-value pairs in this
297
+ * map.
298
+ *
299
+ * @remarks
300
+ *
301
+ * The new map will have the same default value as this map.
302
+ *
303
+ * This function does not mutate the original map instance **unless** you call
304
+ * a mutating function on the map (4th argument) inside the given function.
305
+ *
306
+ * @param fn - Function to call on each key-value pair in the map. The result
307
+ * of this function is used as the values for the entries in the new map.
308
+ *
309
+ * @returns A new map with the entries with new values from calling the given
310
+ * function on each key-value pair in the map.
311
+ */
312
+ mapValues(fn) {
313
+ return this.map((value, key, index, original) => [
314
+ key,
315
+ fn(value, key, index, original)
316
+ ]);
317
+ }
318
+ }
319
+ export {
320
+ DefaultMap
321
+ };