@byloth/core 2.0.0-rc.8 → 2.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.
- package/dist/core.js +3372 -609
- package/dist/core.js.map +1 -1
- package/dist/core.umd.cjs +2 -2
- package/dist/core.umd.cjs.map +1 -1
- package/package.json +13 -10
- package/src/core/types.ts +41 -0
- package/src/helpers.ts +11 -2
- package/src/index.ts +12 -9
- package/src/models/aggregators/aggregated-async-iterator.ts +765 -21
- package/src/models/aggregators/aggregated-iterator.ts +698 -22
- package/src/models/aggregators/reduced-iterator.ts +699 -10
- package/src/models/aggregators/types.ts +153 -10
- package/src/models/callbacks/callable-object.ts +42 -6
- package/src/models/callbacks/index.ts +2 -2
- package/src/models/callbacks/publisher.ts +140 -5
- package/src/models/callbacks/switchable-callback.ts +143 -5
- package/src/models/callbacks/types.ts +16 -0
- package/src/models/exceptions/core.ts +112 -3
- package/src/models/exceptions/index.ts +340 -13
- package/src/models/index.ts +4 -8
- package/src/models/iterators/smart-async-iterator.ts +687 -22
- package/src/models/iterators/smart-iterator.ts +631 -21
- package/src/models/iterators/types.ts +268 -9
- package/src/models/json/json-storage.ts +388 -110
- package/src/models/json/types.ts +10 -1
- package/src/models/promises/deferred-promise.ts +75 -5
- package/src/models/promises/index.ts +1 -3
- package/src/models/promises/smart-promise.ts +232 -4
- package/src/models/promises/timed-promise.ts +38 -1
- package/src/models/promises/types.ts +84 -2
- package/src/models/timers/clock.ts +91 -19
- package/src/models/timers/countdown.ts +152 -22
- package/src/models/timers/game-loop.ts +243 -0
- package/src/models/timers/index.ts +2 -1
- package/src/models/types.ts +6 -5
- package/src/utils/async.ts +43 -0
- package/src/utils/curve.ts +75 -0
- package/src/utils/date.ts +204 -10
- package/src/utils/dom.ts +16 -2
- package/src/utils/index.ts +3 -2
- package/src/utils/iterator.ts +200 -17
- package/src/utils/math.ts +55 -3
- package/src/utils/random.ts +109 -2
- package/src/utils/string.ts +11 -0
- package/src/models/game-loop.ts +0 -83
- package/src/models/promises/long-running-task.ts +0 -294
- package/src/models/promises/thenable.ts +0 -97
|
@@ -2,21 +2,136 @@ import { SmartIterator } from "../iterators/index.js";
|
|
|
2
2
|
import type { GeneratorFunction, IteratorLike } from "../iterators/types.js";
|
|
3
3
|
|
|
4
4
|
import ReducedIterator from "./reduced-iterator.js";
|
|
5
|
-
import type { KeyedIteratee,
|
|
6
|
-
|
|
5
|
+
import type { KeyedIteratee, KeyedTypeGuardPredicate, KeyedReducer } from "./types.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A class representing an iterator that aggregates elements in a lazy and optimized way.
|
|
9
|
+
*
|
|
10
|
+
* It's part of the {@link SmartIterator} implementation, providing a way to group elements of an iterable by key.
|
|
11
|
+
* For this reason, it isn't recommended to instantiate this class directly
|
|
12
|
+
* (although it's still possible), but rather use the {@link SmartIterator.groupBy} method.
|
|
13
|
+
*
|
|
14
|
+
* It isn't directly iterable like its parent class but rather needs to specify on what you want to iterate.
|
|
15
|
+
* See the {@link AggregatedIterator.keys}, {@link AggregatedIterator.entries}
|
|
16
|
+
* & {@link AggregatedIterator.values} methods.
|
|
17
|
+
* It does, however, provide the same set of methods to perform
|
|
18
|
+
* operations and transformation on the elements of the iterator,
|
|
19
|
+
* having also the knowledge and context of the groups to which
|
|
20
|
+
* they belong, allowing to handle them in a grouped manner.
|
|
21
|
+
*
|
|
22
|
+
* This is particularly useful when you need to group elements and
|
|
23
|
+
* then perform specific operations on the groups themselves.
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
27
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
28
|
+
* .count();
|
|
29
|
+
*
|
|
30
|
+
* console.log(results.toObject()); // { odd: 4, even: 4 }
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @template K The type of the keys used to group the elements.
|
|
34
|
+
* @template T The type of the elements to aggregate.
|
|
35
|
+
*/
|
|
7
36
|
export default class AggregatedIterator<K extends PropertyKey, T>
|
|
8
37
|
{
|
|
38
|
+
/**
|
|
39
|
+
* The internal {@link SmartIterator} object that holds the elements to aggregate.
|
|
40
|
+
*/
|
|
9
41
|
protected _elements: SmartIterator<[K, T]>;
|
|
10
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Initializes a new instance of the {@link AggregatedIterator} class.
|
|
45
|
+
*
|
|
46
|
+
* ```ts
|
|
47
|
+
* const iterator = new AggregatedIterator<string, number>([["A", 1], ["B", 2], ["A", 3], ["C", 4], ["B", 5]]);
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @param iterable The iterable to aggregate.
|
|
51
|
+
*/
|
|
11
52
|
public constructor(iterable: Iterable<[K, T]>);
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Initializes a new instance of the {@link AggregatedIterator} class.
|
|
56
|
+
*
|
|
57
|
+
* ```ts
|
|
58
|
+
* import { Random } from "@byloth/core";
|
|
59
|
+
*
|
|
60
|
+
* const iterator = new AggregatedIterator<string, number>({
|
|
61
|
+
* _index: 0,
|
|
62
|
+
* next: () =>
|
|
63
|
+
* {
|
|
64
|
+
* if (this._index >= 5) { return { done: true, value: undefined }; }
|
|
65
|
+
* this._index += 1;
|
|
66
|
+
*
|
|
67
|
+
* return { done: false, value: [Random.Choice(["A", "B", "C"]), (this._index + 1)] };
|
|
68
|
+
* }
|
|
69
|
+
* });
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* @param iterator The iterator to aggregate.
|
|
73
|
+
*/
|
|
12
74
|
public constructor(iterator: Iterator<[K, T]>);
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Initializes a new instance of the {@link AggregatedIterator} class.
|
|
78
|
+
*
|
|
79
|
+
* ```ts
|
|
80
|
+
* import { range, Random } from "@byloth/core";
|
|
81
|
+
*
|
|
82
|
+
* const iterator = new AggregatedIterator<string, number>(function* ()
|
|
83
|
+
* {
|
|
84
|
+
* for (const index of range(5))
|
|
85
|
+
* {
|
|
86
|
+
* yield [Random.Choice(["A", "B", "C"]), (index + 1)];
|
|
87
|
+
* }
|
|
88
|
+
* });
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @param generatorFn The generator function to aggregate.
|
|
92
|
+
*/
|
|
13
93
|
public constructor(generatorFn: GeneratorFunction<[K, T]>);
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Initializes a new instance of the {@link AggregatedIterator} class.
|
|
97
|
+
*
|
|
98
|
+
* ```ts
|
|
99
|
+
* const iterator = new AggregatedIterator(keyedValues);
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* @param argument The iterable, iterator or generator function to aggregate.
|
|
103
|
+
*/
|
|
14
104
|
public constructor(argument: IteratorLike<[K, T]> | GeneratorFunction<[K, T]>);
|
|
15
105
|
public constructor(argument: IteratorLike<[K, T]> | GeneratorFunction<[K, T]>)
|
|
16
106
|
{
|
|
17
107
|
this._elements = new SmartIterator(argument);
|
|
18
108
|
}
|
|
19
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Determines whether all elements of each group of the iterator satisfy a given condition.
|
|
112
|
+
* See also {@link AggregatedIterator.some}.
|
|
113
|
+
* This method will consume the entire iterator in the process.
|
|
114
|
+
*
|
|
115
|
+
* It will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
116
|
+
* Once a single element of one group doesn't satisfy the condition,
|
|
117
|
+
* the result for the respective group will be `false`.
|
|
118
|
+
*
|
|
119
|
+
* Eventually, it will return a new {@link ReducedIterator}
|
|
120
|
+
* object that will contain all the boolean results for each group.
|
|
121
|
+
* If the iterator is infinite, the method will never return.
|
|
122
|
+
*
|
|
123
|
+
* ```ts
|
|
124
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
125
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
126
|
+
* .every((key, value) => value >= 0);
|
|
127
|
+
*
|
|
128
|
+
* console.log(results.toObject()); // { odd: false, even: true }
|
|
129
|
+
* ```
|
|
130
|
+
*
|
|
131
|
+
* @param predicate The condition to check for each element of the iterator.
|
|
132
|
+
*
|
|
133
|
+
* @returns A new {@link ReducedIterator} containing the boolean results for each group.
|
|
134
|
+
*/
|
|
20
135
|
public every(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, boolean>
|
|
21
136
|
{
|
|
22
137
|
const values = new Map<K, [number, boolean]>();
|
|
@@ -35,6 +150,32 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
35
150
|
for (const [key, [_, result]] of values) { yield [key, result]; }
|
|
36
151
|
});
|
|
37
152
|
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Determines whether any elements of each group of the iterator satisfy a given condition.
|
|
156
|
+
* See also {@link AggregatedIterator.every}.
|
|
157
|
+
* This method will consume the entire iterator in the process.
|
|
158
|
+
*
|
|
159
|
+
* It will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
160
|
+
* Once a single element of one group satisfies the condition,
|
|
161
|
+
* the result for the respective group will be `true`.
|
|
162
|
+
*
|
|
163
|
+
* Eventually, it will return a new {@link ReducedIterator}
|
|
164
|
+
* object that will contain all the boolean results for each group.
|
|
165
|
+
* If the iterator is infinite, the method will never return.
|
|
166
|
+
*
|
|
167
|
+
* ```ts
|
|
168
|
+
* const results = new SmartIterator<number>([-5, -4, -3, -2, -1, 0])
|
|
169
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
170
|
+
* .some((key, value) => value >= 0);
|
|
171
|
+
*
|
|
172
|
+
* console.log(results.toObject()); // { odd: false, even: true }
|
|
173
|
+
* ```
|
|
174
|
+
*
|
|
175
|
+
* @param predicate The condition to check for each element of the iterator.
|
|
176
|
+
*
|
|
177
|
+
* @returns A {@link ReducedIterator} containing the boolean results for each group.
|
|
178
|
+
*/
|
|
38
179
|
public some(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, boolean>
|
|
39
180
|
{
|
|
40
181
|
const values = new Map<K, [number, boolean]>();
|
|
@@ -54,8 +195,65 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
54
195
|
});
|
|
55
196
|
}
|
|
56
197
|
|
|
198
|
+
/**
|
|
199
|
+
* Filters the elements of the iterator using a given condition.
|
|
200
|
+
*
|
|
201
|
+
* This method will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
202
|
+
* If the condition is met, the element will be included in the new iterator.
|
|
203
|
+
*
|
|
204
|
+
* Since the iterator is lazy, the filtering process will
|
|
205
|
+
* be executed once the resulting iterator is materialized.
|
|
206
|
+
*
|
|
207
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
208
|
+
* This means that the original iterator won't be consumed until the
|
|
209
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
210
|
+
*
|
|
211
|
+
* ```ts
|
|
212
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
213
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
214
|
+
* .filter((key, value) => value >= 0);
|
|
215
|
+
*
|
|
216
|
+
* console.log(results.toObject()); // { odd: [3, 5], even: [0, 2, 6, 8] }
|
|
217
|
+
* ```
|
|
218
|
+
*
|
|
219
|
+
* @param predicate The condition to check for each element of the iterator.
|
|
220
|
+
*
|
|
221
|
+
* @returns A new {@link AggregatedIterator} containing only the elements that satisfy the condition.
|
|
222
|
+
*/
|
|
57
223
|
public filter(predicate: KeyedIteratee<K, T, boolean>): AggregatedIterator<K, T>;
|
|
58
|
-
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Filters the elements of the iterator using a given condition.
|
|
227
|
+
*
|
|
228
|
+
* This method will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
229
|
+
* If the condition is met, the element will be included in the new iterator.
|
|
230
|
+
*
|
|
231
|
+
* Since the iterator is lazy, the filtering process will
|
|
232
|
+
* be executed once the resulting iterator is materialized.
|
|
233
|
+
*
|
|
234
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
235
|
+
* This means that the original iterator won't be consumed until the
|
|
236
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
237
|
+
*
|
|
238
|
+
* ```ts
|
|
239
|
+
* const results = new SmartIterator<number | string>([-3, "-1", 0, "2", "3", 5, 6, "8"])
|
|
240
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
241
|
+
* .filter<number>((key, value) => typeof value === "number");
|
|
242
|
+
*
|
|
243
|
+
* console.log(results.toObject()); // { odd: [-3, 5], even: [0, 6] }
|
|
244
|
+
* ```
|
|
245
|
+
*
|
|
246
|
+
* @template S
|
|
247
|
+
* The type of the elements that satisfy the condition.
|
|
248
|
+
* This allows the type-system to infer the correct type of the new iterator.
|
|
249
|
+
*
|
|
250
|
+
* It must be a subtype of the original type of the elements.
|
|
251
|
+
*
|
|
252
|
+
* @param predicate The type guard condition to check for each element of the iterator.
|
|
253
|
+
*
|
|
254
|
+
* @returns A new {@link AggregatedIterator} containing only the elements that satisfy the condition.
|
|
255
|
+
*/
|
|
256
|
+
public filter<S extends T>(predicate: KeyedTypeGuardPredicate<K, T, S>): AggregatedIterator<K, S>;
|
|
59
257
|
public filter(predicate: KeyedIteratee<K, T, boolean>): AggregatedIterator<K, T>
|
|
60
258
|
{
|
|
61
259
|
const elements = this._elements;
|
|
@@ -63,17 +261,43 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
63
261
|
return new AggregatedIterator(function* ()
|
|
64
262
|
{
|
|
65
263
|
const indexes = new Map<K, number>();
|
|
66
|
-
|
|
67
264
|
for (const [key, element] of elements)
|
|
68
265
|
{
|
|
69
266
|
const index = indexes.get(key) ?? 0;
|
|
70
|
-
|
|
71
267
|
if (predicate(key, element, index)) { yield [key, element]; }
|
|
72
268
|
|
|
73
269
|
indexes.set(key, index + 1);
|
|
74
270
|
}
|
|
75
271
|
});
|
|
76
272
|
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Maps the elements of the iterator using a given transformation function.
|
|
276
|
+
*
|
|
277
|
+
* This method will iterate over all elements of the iterator applying the transformation function.
|
|
278
|
+
* The result of each transformation will be included in the new iterator.
|
|
279
|
+
*
|
|
280
|
+
* Since the iterator is lazy, the mapping process will
|
|
281
|
+
* be executed once the resulting iterator is materialized.
|
|
282
|
+
*
|
|
283
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
284
|
+
* This means that the original iterator won't be consumed until the
|
|
285
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
286
|
+
*
|
|
287
|
+
* ```ts
|
|
288
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
289
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
290
|
+
* .map((key, value) => Math.abs(value));
|
|
291
|
+
*
|
|
292
|
+
* console.log(results.toObject()); // { odd: [3, 1, 3, 5], even: [0, 2, 6, 8] }
|
|
293
|
+
* ```
|
|
294
|
+
*
|
|
295
|
+
* @template V The type of the elements after the transformation.
|
|
296
|
+
*
|
|
297
|
+
* @param iteratee The transformation function to apply to each element of the iterator.
|
|
298
|
+
*
|
|
299
|
+
* @returns A new {@link AggregatedIterator} containing the transformed elements.
|
|
300
|
+
*/
|
|
77
301
|
public map<V>(iteratee: KeyedIteratee<K, T, V>): AggregatedIterator<K, V>
|
|
78
302
|
{
|
|
79
303
|
const elements = this._elements;
|
|
@@ -81,20 +305,106 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
81
305
|
return new AggregatedIterator(function* ()
|
|
82
306
|
{
|
|
83
307
|
const indexes = new Map<K, number>();
|
|
84
|
-
|
|
85
308
|
for (const [key, element] of elements)
|
|
86
309
|
{
|
|
87
310
|
const index = indexes.get(key) ?? 0;
|
|
88
|
-
|
|
89
311
|
yield [key, iteratee(key, element, index)];
|
|
90
312
|
|
|
91
313
|
indexes.set(key, index + 1);
|
|
92
314
|
}
|
|
93
315
|
});
|
|
94
316
|
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Reduces the elements of the iterator using a given reducer function.
|
|
320
|
+
* This method will consume the entire iterator in the process.
|
|
321
|
+
*
|
|
322
|
+
* It will iterate over all elements of the iterator applying the reducer function.
|
|
323
|
+
* The result of each iteration will be passed as the accumulator to the next one.
|
|
324
|
+
*
|
|
325
|
+
* The first accumulator value will be the first element of the iterator.
|
|
326
|
+
* The last accumulator value will be the final result of the reduction.
|
|
327
|
+
*
|
|
328
|
+
* Eventually, it will return a new {@link ReducedIterator}
|
|
329
|
+
* object that will contain all the reduced results for each group.
|
|
330
|
+
* If the iterator is infinite, the method will never return.
|
|
331
|
+
*
|
|
332
|
+
* ```ts
|
|
333
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
334
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
335
|
+
* .reduce((key, accumulator, value) => accumulator + value);
|
|
336
|
+
*
|
|
337
|
+
* console.log(results.toObject()); // { odd: 4, even: 16 }
|
|
338
|
+
* ```
|
|
339
|
+
*
|
|
340
|
+
* @param reducer The reducer function to apply to each element of the iterator.
|
|
341
|
+
*
|
|
342
|
+
* @returns A new {@link ReducedIterator} containing the reduced results for each group.
|
|
343
|
+
*/
|
|
95
344
|
public reduce(reducer: KeyedReducer<K, T, T>): ReducedIterator<K, T>;
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Reduces the elements of the iterator using a given reducer function.
|
|
348
|
+
* This method will consume the entire iterator in the process.
|
|
349
|
+
*
|
|
350
|
+
* It will iterate over all elements of the iterator applying the reducer function.
|
|
351
|
+
* The result of each iteration will be passed as the accumulator to the next one.
|
|
352
|
+
*
|
|
353
|
+
* The first accumulator value will be the provided initial value.
|
|
354
|
+
* The last accumulator value will be the final result of the reduction.
|
|
355
|
+
*
|
|
356
|
+
* Eventually, it will return a new {@link ReducedIterator}
|
|
357
|
+
* object that will contain all the reduced results for each group.
|
|
358
|
+
* If the iterator is infinite, the method will never return.
|
|
359
|
+
*
|
|
360
|
+
* ```ts
|
|
361
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
362
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
363
|
+
* .reduce((key, accumulator, value) => accumulator + value, 0);
|
|
364
|
+
*
|
|
365
|
+
* console.log(results.toObject()); // { odd: 4, even: 16 }
|
|
366
|
+
* ```
|
|
367
|
+
*
|
|
368
|
+
* @template A The type of the accumulator value which will also be the type of the final result of the reduction.
|
|
369
|
+
*
|
|
370
|
+
* @param reducer The reducer function to apply to each element of the iterator.
|
|
371
|
+
* @param initialValue The initial value of the accumulator.
|
|
372
|
+
*
|
|
373
|
+
* @returns A new {@link ReducedIterator} containing the reduced results for each group.
|
|
374
|
+
*/
|
|
375
|
+
public reduce<A extends PropertyKey>(reducer: KeyedReducer<K, T, A>, initialValue: A): ReducedIterator<K, A>;
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Reduces the elements of the iterator using a given reducer function.
|
|
379
|
+
* This method will consume the entire iterator in the process.
|
|
380
|
+
*
|
|
381
|
+
* It will iterate over all elements of the iterator applying the reducer function.
|
|
382
|
+
* The result of each iteration will be passed as the accumulator to the next one.
|
|
383
|
+
*
|
|
384
|
+
* The first accumulator value will be the provided initial value by the given function.
|
|
385
|
+
* The last accumulator value will be the final result of the reduction.
|
|
386
|
+
*
|
|
387
|
+
* Eventually, it will return a new {@link ReducedIterator}
|
|
388
|
+
* object that will contain all the reduced results for each group.
|
|
389
|
+
* If the iterator is infinite, the method will never return.
|
|
390
|
+
*
|
|
391
|
+
* ```ts
|
|
392
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
393
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
394
|
+
* .reduce((key, { value }, currentValue) => ({ value: value + currentValue }), (key) => ({ value: 0 }));
|
|
395
|
+
*
|
|
396
|
+
* console.log(results.toObject()); // { odd: { value: 4 }, even: { value: 16 } }
|
|
397
|
+
* ```
|
|
398
|
+
*
|
|
399
|
+
* @template A The type of the accumulator value which will also be the type of the final result of the reduction.
|
|
400
|
+
*
|
|
401
|
+
* @param reducer The reducer function to apply to each element of the iterator.
|
|
402
|
+
* @param initialValue The function that provides the initial value for the accumulator.
|
|
403
|
+
*
|
|
404
|
+
* @returns A new {@link ReducedIterator} containing the reduced results for each group.
|
|
405
|
+
*/
|
|
96
406
|
public reduce<A>(reducer: KeyedReducer<K, T, A>, initialValue: (key: K) => A): ReducedIterator<K, A>;
|
|
97
|
-
public reduce<A>(reducer: KeyedReducer<K, T, A>, initialValue?: (key: K) => A): ReducedIterator<K, A>
|
|
407
|
+
public reduce<A>(reducer: KeyedReducer<K, T, A>, initialValue?: A | ((key: K) => A)): ReducedIterator<K, A>
|
|
98
408
|
{
|
|
99
409
|
const values = new Map<K, [number, A]>();
|
|
100
410
|
|
|
@@ -107,7 +417,9 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
107
417
|
else if (initialValue !== undefined)
|
|
108
418
|
{
|
|
109
419
|
index = 0;
|
|
110
|
-
|
|
420
|
+
|
|
421
|
+
if (initialValue instanceof Function) { accumulator = initialValue(key); }
|
|
422
|
+
else { accumulator = initialValue; }
|
|
111
423
|
}
|
|
112
424
|
else
|
|
113
425
|
{
|
|
@@ -125,26 +437,84 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
125
437
|
});
|
|
126
438
|
}
|
|
127
439
|
|
|
128
|
-
|
|
440
|
+
/**
|
|
441
|
+
* Flattens the elements of the iterator using a given transformation function.
|
|
442
|
+
*
|
|
443
|
+
* This method will iterate over all elements of the iterator applying the transformation function.
|
|
444
|
+
* The result of each transformation will be included in the new iterator.
|
|
445
|
+
*
|
|
446
|
+
* Since the iterator is lazy, the flattening process will
|
|
447
|
+
* be executed once the resulting iterator is materialized.
|
|
448
|
+
*
|
|
449
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
450
|
+
* This means that the original iterator won't be consumed until the
|
|
451
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
452
|
+
*
|
|
453
|
+
* ```ts
|
|
454
|
+
* const results = new SmartIterator<number[]>([[-3, -1], 0, 2, 3, 5, [6, 8]])
|
|
455
|
+
* .groupBy((values) =>
|
|
456
|
+
* {
|
|
457
|
+
* const value = values instanceof Array ? values[0] : values;
|
|
458
|
+
* return value % 2 === 0 ? "even" : "odd";
|
|
459
|
+
* })
|
|
460
|
+
* .flatMap((key, values) => values);
|
|
461
|
+
*
|
|
462
|
+
* console.log(results.toObject()); // { odd: [-3, -1, 3, 5], even: [0, 2, 6, 8] }
|
|
463
|
+
* ```
|
|
464
|
+
*
|
|
465
|
+
* @template V The type of the elements after the transformation.
|
|
466
|
+
*
|
|
467
|
+
* @param iteratee The transformation function to apply to each element of the iterator.
|
|
468
|
+
*
|
|
469
|
+
* @returns A new {@link AggregatedIterator} containing the transformed elements.
|
|
470
|
+
*/
|
|
471
|
+
public flatMap<V>(iteratee: KeyedIteratee<K, T, V | readonly V[]>): AggregatedIterator<K, V>
|
|
129
472
|
{
|
|
130
473
|
const elements = this._elements;
|
|
131
474
|
|
|
132
475
|
return new AggregatedIterator(function* ()
|
|
133
476
|
{
|
|
134
477
|
const indexes = new Map<K, number>();
|
|
135
|
-
|
|
136
478
|
for (const [key, element] of elements)
|
|
137
479
|
{
|
|
138
480
|
const index = indexes.get(key) ?? 0;
|
|
139
481
|
const values = iteratee(key, element, index);
|
|
140
482
|
|
|
141
|
-
|
|
483
|
+
if (values instanceof Array)
|
|
484
|
+
{
|
|
485
|
+
for (const value of values) { yield [key, value]; }
|
|
486
|
+
}
|
|
487
|
+
else { yield [key, values]; }
|
|
142
488
|
|
|
143
489
|
indexes.set(key, index + 1);
|
|
144
490
|
}
|
|
145
491
|
});
|
|
146
492
|
}
|
|
147
493
|
|
|
494
|
+
/**
|
|
495
|
+
* Drops a given number of elements from the beginning of each group of the iterator.
|
|
496
|
+
* The remaining elements will be included in the new iterator.
|
|
497
|
+
* See also {@link AggregatedIterator.take}.
|
|
498
|
+
*
|
|
499
|
+
* Since the iterator is lazy, the dropping process will
|
|
500
|
+
* be executed once the resulting iterator is materialized.
|
|
501
|
+
*
|
|
502
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
503
|
+
* This means that the original iterator won't be consumed until the
|
|
504
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
505
|
+
*
|
|
506
|
+
* ```ts
|
|
507
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
508
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
509
|
+
* .drop(2);
|
|
510
|
+
*
|
|
511
|
+
* console.log(results.toObject()); // { odd: [3, 5], even: [6, 8] }
|
|
512
|
+
* ```
|
|
513
|
+
*
|
|
514
|
+
* @param count The number of elements to drop from the beginning of each group.
|
|
515
|
+
*
|
|
516
|
+
* @returns A new {@link AggregatedIterator} containing the remaining elements.
|
|
517
|
+
*/
|
|
148
518
|
public drop(count: number): AggregatedIterator<K, T>
|
|
149
519
|
{
|
|
150
520
|
const elements = this._elements;
|
|
@@ -152,7 +522,6 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
152
522
|
return new AggregatedIterator(function* ()
|
|
153
523
|
{
|
|
154
524
|
const indexes = new Map<K, number>();
|
|
155
|
-
|
|
156
525
|
for (const [key, element] of elements)
|
|
157
526
|
{
|
|
158
527
|
const index = indexes.get(key) ?? 0;
|
|
@@ -167,6 +536,31 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
167
536
|
}
|
|
168
537
|
});
|
|
169
538
|
}
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Takes a given number of elements from the beginning of each group of the iterator.
|
|
542
|
+
* The elements will be included in the new iterator.
|
|
543
|
+
* See also {@link AggregatedIterator.drop}.
|
|
544
|
+
*
|
|
545
|
+
* Since the iterator is lazy, the taking process will
|
|
546
|
+
* be executed once the resulting iterator is materialized.
|
|
547
|
+
*
|
|
548
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
549
|
+
* This means that the original iterator won't be consumed until the
|
|
550
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
551
|
+
*
|
|
552
|
+
* ```ts
|
|
553
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
554
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
555
|
+
* .take(2);
|
|
556
|
+
*
|
|
557
|
+
* console.log(results.toObject()); // { odd: [-3, -1], even: [0, 2] }
|
|
558
|
+
* ```
|
|
559
|
+
*
|
|
560
|
+
* @param count The number of elements to take from the beginning of each group.
|
|
561
|
+
*
|
|
562
|
+
* @returns A new {@link AggregatedIterator} containing the taken elements.
|
|
563
|
+
*/
|
|
170
564
|
public take(limit: number): AggregatedIterator<K, T>
|
|
171
565
|
{
|
|
172
566
|
const elements = this._elements;
|
|
@@ -174,12 +568,10 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
174
568
|
return new AggregatedIterator(function* ()
|
|
175
569
|
{
|
|
176
570
|
const indexes = new Map<K, number>();
|
|
177
|
-
|
|
178
571
|
for (const [key, element] of elements)
|
|
179
572
|
{
|
|
180
573
|
const index = indexes.get(key) ?? 0;
|
|
181
574
|
if (index >= limit) { continue; }
|
|
182
|
-
|
|
183
575
|
yield [key, element];
|
|
184
576
|
|
|
185
577
|
indexes.set(key, index + 1);
|
|
@@ -187,8 +579,63 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
187
579
|
});
|
|
188
580
|
}
|
|
189
581
|
|
|
582
|
+
/**
|
|
583
|
+
* Finds the first element of each group of the iterator that satisfies a given condition.
|
|
584
|
+
* This method will consume the entire iterator in the process.
|
|
585
|
+
*
|
|
586
|
+
* It will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
587
|
+
* Once the first element of one group satisfies the condition,
|
|
588
|
+
* the result for the respective group will be the element itself.
|
|
589
|
+
*
|
|
590
|
+
* Eventually, it will return a new {@link ReducedIterator}
|
|
591
|
+
* object that will contain the first element that satisfies the condition for each group.
|
|
592
|
+
* If the iterator is infinite, the method will never return.
|
|
593
|
+
*
|
|
594
|
+
* ```ts
|
|
595
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
596
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
597
|
+
* .find((key, value) => value > 0);
|
|
598
|
+
*
|
|
599
|
+
* console.log(results.toObject()); // { odd: 3, even: 2 }
|
|
600
|
+
* ```
|
|
601
|
+
*
|
|
602
|
+
* @param predicate The condition to check for each element of the iterator.
|
|
603
|
+
*
|
|
604
|
+
* @returns A new {@link ReducedIterator} containing the first element that satisfies the condition for each group.
|
|
605
|
+
*/
|
|
190
606
|
public find(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, T | undefined>;
|
|
191
|
-
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Finds the first element of each group of the iterator that satisfies a given condition.
|
|
610
|
+
* This method will consume the entire iterator in the process.
|
|
611
|
+
*
|
|
612
|
+
* It will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
613
|
+
* Once the first element of one group satisfies the condition,
|
|
614
|
+
* the result for the respective group will be the element itself.
|
|
615
|
+
*
|
|
616
|
+
* Eventually, it will return a new {@link ReducedIterator}
|
|
617
|
+
* object that will contain the first element that satisfies the condition for each group.
|
|
618
|
+
* If the iterator is infinite, the method will never return.
|
|
619
|
+
*
|
|
620
|
+
* ```ts
|
|
621
|
+
* const results = new SmartIterator<number | string>([-3, "-1", 0, "2", "3", 5, 6, "8"])
|
|
622
|
+
* .groupBy((value) => Number(value) % 2 === 0 ? "even" : "odd")
|
|
623
|
+
* .find<number>((key, value) => typeof value === "number");
|
|
624
|
+
*
|
|
625
|
+
* console.log(results.toObject()); // { odd: -3, even: 0 }
|
|
626
|
+
* ```
|
|
627
|
+
*
|
|
628
|
+
* @template S
|
|
629
|
+
* The type of the elements that satisfy the condition.
|
|
630
|
+
* This allows the type-system to infer the correct type of the new iterator.
|
|
631
|
+
*
|
|
632
|
+
* It must be a subtype of the original type of the elements.
|
|
633
|
+
*
|
|
634
|
+
* @param predicate The type guard condition to check for each element of the iterator.
|
|
635
|
+
*
|
|
636
|
+
* @returns A new {@link ReducedIterator} containing the first element that satisfies the condition for each group.
|
|
637
|
+
*/
|
|
638
|
+
public find<S extends T>(predicate: KeyedTypeGuardPredicate<K, T, S>): ReducedIterator<K, S | undefined>;
|
|
192
639
|
public find(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, T | undefined>
|
|
193
640
|
{
|
|
194
641
|
const values = new Map<K, [number, T | undefined]>();
|
|
@@ -209,10 +656,53 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
209
656
|
});
|
|
210
657
|
}
|
|
211
658
|
|
|
659
|
+
/**
|
|
660
|
+
* Enumerates the elements of the iterator.
|
|
661
|
+
* Each element is paired with its index within the group in a new iterator.
|
|
662
|
+
*
|
|
663
|
+
* Since the iterator is lazy, the enumeration process will
|
|
664
|
+
* be executed once the resulting iterator is materialized.
|
|
665
|
+
*
|
|
666
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
667
|
+
* This means that the original iterator won't be consumed until the
|
|
668
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
669
|
+
*
|
|
670
|
+
* ```ts
|
|
671
|
+
* const results = new SmartIterator<number>([-3, 0, 2, -1, 3])
|
|
672
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
673
|
+
* .enumerate();
|
|
674
|
+
*
|
|
675
|
+
* console.log(results.toObject()); // { odd: [[0, -3], [1, -1], [2, 3]], even: [[0, 0], [1, 2]] }
|
|
676
|
+
* ```
|
|
677
|
+
*
|
|
678
|
+
* @returns A new {@link AggregatedIterator} containing the enumerated elements.
|
|
679
|
+
*/
|
|
212
680
|
public enumerate(): AggregatedIterator<K, [number, T]>
|
|
213
681
|
{
|
|
214
682
|
return this.map((_, value, index) => [index, value]);
|
|
215
683
|
}
|
|
684
|
+
|
|
685
|
+
/**
|
|
686
|
+
* Removes all duplicate elements from within each group of the iterator.
|
|
687
|
+
* The first occurrence of each element will be included in the new iterator.
|
|
688
|
+
*
|
|
689
|
+
* Since the iterator is lazy, the deduplication process will
|
|
690
|
+
* be executed once the resulting iterator is materialized.
|
|
691
|
+
*
|
|
692
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
693
|
+
* This means that the original iterator won't be consumed until the
|
|
694
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
695
|
+
*
|
|
696
|
+
* ```ts
|
|
697
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 6, -3, -1, 0, 5, 6, 8, 0, 2])
|
|
698
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
699
|
+
* .unique();
|
|
700
|
+
*
|
|
701
|
+
* console.log(results.toObject()); // { odd: [-3, -1, 3, 5], even: [0, 2, 6, 8] }
|
|
702
|
+
* ```
|
|
703
|
+
*
|
|
704
|
+
* @returns A new {@link AggregatedIterator} containing only the unique elements.
|
|
705
|
+
*/
|
|
216
706
|
public unique(): AggregatedIterator<K, T>
|
|
217
707
|
{
|
|
218
708
|
const elements = this._elements;
|
|
@@ -220,11 +710,9 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
220
710
|
return new AggregatedIterator(function* ()
|
|
221
711
|
{
|
|
222
712
|
const keys = new Map<K, Set<T>>();
|
|
223
|
-
|
|
224
713
|
for (const [key, element] of elements)
|
|
225
714
|
{
|
|
226
715
|
const values = keys.get(key) ?? new Set<T>();
|
|
227
|
-
|
|
228
716
|
if (values.has(element)) { continue; }
|
|
229
717
|
|
|
230
718
|
values.add(element);
|
|
@@ -235,6 +723,22 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
235
723
|
});
|
|
236
724
|
}
|
|
237
725
|
|
|
726
|
+
/**
|
|
727
|
+
* Counts the number of elements within each group of the iterator.
|
|
728
|
+
* This method will consume the entire iterator in the process.
|
|
729
|
+
*
|
|
730
|
+
* If the iterator is infinite, the method will never return.
|
|
731
|
+
*
|
|
732
|
+
* ```ts
|
|
733
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
734
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
735
|
+
* .count();
|
|
736
|
+
*
|
|
737
|
+
* console.log(results.toObject()); // { odd: 4, even: 4 }
|
|
738
|
+
* ```
|
|
739
|
+
*
|
|
740
|
+
* @returns A new {@link ReducedIterator} containing the number of elements for each group.
|
|
741
|
+
*/
|
|
238
742
|
public count(): ReducedIterator<K, number>
|
|
239
743
|
{
|
|
240
744
|
const counters = new Map<K, number>();
|
|
@@ -252,20 +756,101 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
252
756
|
});
|
|
253
757
|
}
|
|
254
758
|
|
|
759
|
+
/**
|
|
760
|
+
* Iterates over the elements of the iterator.
|
|
761
|
+
* The elements are passed to the given iteratee function along with their key and index within the group.
|
|
762
|
+
*
|
|
763
|
+
* This method will consume the entire iterator in the process.
|
|
764
|
+
* If the iterator is infinite, the method will never return.
|
|
765
|
+
*
|
|
766
|
+
* ```ts
|
|
767
|
+
* const aggregator = new SmartIterator<number>([-3, 0, 2, -1, 3])
|
|
768
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd");
|
|
769
|
+
*
|
|
770
|
+
* aggregator.forEach((key, value, index) =>
|
|
771
|
+
* {
|
|
772
|
+
* console.log(`${index}: ${value}`); // "0: -3", "0: 0", "1: 2", "1: -1", "2: 3"
|
|
773
|
+
* };
|
|
774
|
+
* ```
|
|
775
|
+
*
|
|
776
|
+
* @param iteratee The function to execute for each element of the iterator.
|
|
777
|
+
*/
|
|
255
778
|
public forEach(iteratee: KeyedIteratee<K, T>): void
|
|
256
779
|
{
|
|
257
780
|
const indexes = new Map<K, number>();
|
|
258
|
-
|
|
259
781
|
for (const [key, element] of this._elements)
|
|
260
782
|
{
|
|
261
783
|
const index = indexes.get(key) ?? 0;
|
|
262
|
-
|
|
263
784
|
iteratee(key, element, index);
|
|
264
785
|
|
|
265
786
|
indexes.set(key, index + 1);
|
|
266
787
|
}
|
|
267
788
|
}
|
|
268
789
|
|
|
790
|
+
/**
|
|
791
|
+
* Changes the key of each element on which the iterator is aggregated.
|
|
792
|
+
* The new key is determined by the given iteratee function.
|
|
793
|
+
*
|
|
794
|
+
* Since the iterator is lazy, the reorganization process will
|
|
795
|
+
* be executed once the resulting iterator is materialized.
|
|
796
|
+
*
|
|
797
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
798
|
+
* This means that the original iterator won't be consumed until the
|
|
799
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
800
|
+
*
|
|
801
|
+
* ```ts
|
|
802
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
803
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
804
|
+
* .map((key, value, index) => index % 2 === 0 ? value : -value)
|
|
805
|
+
* .reorganizeBy((key, value) => value >= 0 ? "+" : "-");
|
|
806
|
+
*
|
|
807
|
+
* console.log(results.toObject()); // { "+": [1, 0, 3, 6], "-": [-3, -2, -5, -8] }
|
|
808
|
+
* ```
|
|
809
|
+
*
|
|
810
|
+
* @template J The type of the new key.
|
|
811
|
+
*
|
|
812
|
+
* @param iteratee The function to determine the new key for each element of the iterator.
|
|
813
|
+
*
|
|
814
|
+
* @returns A new {@link AggregatedIterator} containing the elements reorganized by the new keys.
|
|
815
|
+
*/
|
|
816
|
+
public reorganizeBy<J extends PropertyKey>(iteratee: KeyedIteratee<K, T, J>): AggregatedIterator<J, T>
|
|
817
|
+
{
|
|
818
|
+
const elements = this._elements;
|
|
819
|
+
|
|
820
|
+
return new AggregatedIterator(function* ()
|
|
821
|
+
{
|
|
822
|
+
const indexes = new Map<K, number>();
|
|
823
|
+
for (const [key, element] of elements)
|
|
824
|
+
{
|
|
825
|
+
const index = indexes.get(key) ?? 0;
|
|
826
|
+
yield [iteratee(key, element, index), element];
|
|
827
|
+
|
|
828
|
+
indexes.set(key, index + 1);
|
|
829
|
+
}
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
/**
|
|
834
|
+
* An utility method that returns a new {@link SmartIterator}
|
|
835
|
+
* object containing all the keys of the iterator.
|
|
836
|
+
*
|
|
837
|
+
* Since the iterator is lazy, the keys will be extracted
|
|
838
|
+
* be executed once the resulting iterator is materialized.
|
|
839
|
+
*
|
|
840
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
841
|
+
* This means that the original iterator won't be consumed until the
|
|
842
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
843
|
+
*
|
|
844
|
+
* ```ts
|
|
845
|
+
* const keys = new SmartIterator([-3, Symbol(), "A", { }, null, [1 , 2, 3], false])
|
|
846
|
+
* .groupBy((value) => typeof value)
|
|
847
|
+
* .keys();
|
|
848
|
+
*
|
|
849
|
+
* console.log(keys.toArray()); // ["number", "symbol", "string", "object", "boolean"]
|
|
850
|
+
* ```
|
|
851
|
+
*
|
|
852
|
+
* @returns A new {@link SmartIterator} containing all the keys of the iterator.
|
|
853
|
+
*/
|
|
269
854
|
public keys(): SmartIterator<K>
|
|
270
855
|
{
|
|
271
856
|
const elements = this._elements;
|
|
@@ -273,7 +858,6 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
273
858
|
return new SmartIterator<K>(function* ()
|
|
274
859
|
{
|
|
275
860
|
const keys = new Set<K>();
|
|
276
|
-
|
|
277
861
|
for (const [key] of elements)
|
|
278
862
|
{
|
|
279
863
|
if (keys.has(key)) { continue; }
|
|
@@ -283,10 +867,55 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
283
867
|
}
|
|
284
868
|
});
|
|
285
869
|
}
|
|
286
|
-
|
|
870
|
+
|
|
871
|
+
/**
|
|
872
|
+
* An utility method that returns a new {@link SmartIterator}
|
|
873
|
+
* object containing all the entries of the iterator.
|
|
874
|
+
* Each entry is a tuple containing the key and the element.
|
|
875
|
+
*
|
|
876
|
+
* Since the iterator is lazy, the entries will be extracted
|
|
877
|
+
* be executed once the resulting iterator is materialized.
|
|
878
|
+
*
|
|
879
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
880
|
+
* This means that the original iterator won't be consumed until the
|
|
881
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
882
|
+
*
|
|
883
|
+
* ```ts
|
|
884
|
+
* const entries = new SmartIterator<number>([-3, 0, 2, -1, 3])
|
|
885
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
886
|
+
* .entries();
|
|
887
|
+
*
|
|
888
|
+
* console.log(entries.toArray()); // [["odd", -3], ["even", 0], ["even", 2], ["odd", -1], ["odd", 3]]
|
|
889
|
+
* ```
|
|
890
|
+
*
|
|
891
|
+
* @returns A new {@link SmartIterator} containing all the entries of the iterator.
|
|
892
|
+
*/
|
|
893
|
+
public entries(): SmartIterator<[K, T]>
|
|
287
894
|
{
|
|
288
895
|
return this._elements;
|
|
289
896
|
}
|
|
897
|
+
|
|
898
|
+
/**
|
|
899
|
+
* An utility method that returns a new {@link SmartIterator}
|
|
900
|
+
* object containing all the values of the iterator.
|
|
901
|
+
*
|
|
902
|
+
* Since the iterator is lazy, the values will be extracted
|
|
903
|
+
* be executed once the resulting iterator is materialized.
|
|
904
|
+
*
|
|
905
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
906
|
+
* This means that the original iterator won't be consumed until the
|
|
907
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
908
|
+
*
|
|
909
|
+
* ```ts
|
|
910
|
+
* const values = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
911
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
912
|
+
* .values();
|
|
913
|
+
*
|
|
914
|
+
* console.log(values.toArray()); // [-3, -1, 0, 2, 3, 5, 6, 8]
|
|
915
|
+
* ```
|
|
916
|
+
*
|
|
917
|
+
* @returns A new {@link SmartIterator} containing all the values of the iterator.
|
|
918
|
+
*/
|
|
290
919
|
public values(): SmartIterator<T>
|
|
291
920
|
{
|
|
292
921
|
const elements = this._elements;
|
|
@@ -297,12 +926,43 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
297
926
|
});
|
|
298
927
|
}
|
|
299
928
|
|
|
929
|
+
/**
|
|
930
|
+
* Materializes the iterator into an array of arrays.
|
|
931
|
+
* This method will consume the entire iterator in the process.
|
|
932
|
+
*
|
|
933
|
+
* If the iterator is infinite, the method will never return.
|
|
934
|
+
*
|
|
935
|
+
* ```ts
|
|
936
|
+
* const aggregator = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
937
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd");
|
|
938
|
+
*
|
|
939
|
+
* console.log(aggregator.toArray()); // [[-3, -1, 3, 5], [0, 2, 6, 8]]
|
|
940
|
+
* ```
|
|
941
|
+
*
|
|
942
|
+
* @returns An {@link Array} of arrays containing the elements of the iterator.
|
|
943
|
+
*/
|
|
300
944
|
public toArray(): T[][]
|
|
301
945
|
{
|
|
302
946
|
const map = this.toMap();
|
|
303
947
|
|
|
304
948
|
return Array.from(map.values());
|
|
305
949
|
}
|
|
950
|
+
|
|
951
|
+
/**
|
|
952
|
+
* Materializes the iterator into a map.
|
|
953
|
+
* This method will consume the entire iterator in the process.
|
|
954
|
+
*
|
|
955
|
+
* If the iterator is infinite, the method will never return.
|
|
956
|
+
*
|
|
957
|
+
* ```ts
|
|
958
|
+
* const aggregator = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
959
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd");
|
|
960
|
+
*
|
|
961
|
+
* console.log(aggregator.toMap()); // Map(2) { "odd" => [-3, -1, 3, 5], "even" => [0, 2, 6, 8] }
|
|
962
|
+
* ```
|
|
963
|
+
*
|
|
964
|
+
* @returns A {@link Map} containing the elements of the iterator.
|
|
965
|
+
*/
|
|
306
966
|
public toMap(): Map<K, T[]>
|
|
307
967
|
{
|
|
308
968
|
const groups = new Map<K, T[]>();
|
|
@@ -317,6 +977,22 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
317
977
|
|
|
318
978
|
return groups;
|
|
319
979
|
}
|
|
980
|
+
|
|
981
|
+
/**
|
|
982
|
+
* Materializes the iterator into an object.
|
|
983
|
+
* This method will consume the entire iterator in the process.
|
|
984
|
+
*
|
|
985
|
+
* If the iterator is infinite, the method will never return.
|
|
986
|
+
*
|
|
987
|
+
* ```ts
|
|
988
|
+
* const aggregator = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
989
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd");
|
|
990
|
+
*
|
|
991
|
+
* console.log(aggregator.toObject()); // { odd: [-3, -1, 3, 5], even: [0, 2, 6, 8] }
|
|
992
|
+
* ```
|
|
993
|
+
*
|
|
994
|
+
* @returns An {@link Object} containing the elements of the iterator.
|
|
995
|
+
*/
|
|
320
996
|
public toObject(): Record<K, T[]>
|
|
321
997
|
{
|
|
322
998
|
const groups = { } as Record<K, T[]>;
|