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