@byloth/core 2.0.0-rc.9 → 2.0.1
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 +4087 -621
- 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 +17 -13
- 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 +920 -21
- package/src/models/aggregators/aggregated-iterator.ts +838 -22
- package/src/models/aggregators/reduced-iterator.ts +827 -11
- 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 +160 -4
- package/src/models/callbacks/switchable-callback.ts +230 -23
- package/src/models/callbacks/types.ts +16 -0
- package/src/models/exceptions/core.ts +132 -3
- package/src/models/exceptions/index.ts +405 -13
- package/src/models/index.ts +4 -8
- package/src/models/iterators/smart-async-iterator.ts +827 -22
- package/src/models/iterators/smart-iterator.ts +755 -20
- package/src/models/iterators/types.ts +268 -9
- package/src/models/json/json-storage.ts +508 -110
- package/src/models/json/types.ts +10 -1
- package/src/models/promises/deferred-promise.ts +85 -5
- package/src/models/promises/index.ts +1 -3
- package/src/models/promises/smart-promise.ts +272 -4
- package/src/models/promises/timed-promise.ts +43 -1
- package/src/models/promises/types.ts +84 -2
- package/src/models/timers/clock.ts +109 -19
- package/src/models/timers/countdown.ts +176 -21
- package/src/models/timers/game-loop.ts +266 -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 +85 -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 +139 -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,161 @@ 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
|
+
* ---
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* const iterator = new AggregatedIterator<string, number>([["A", 1], ["B", 2], ["A", 3], ["C", 4], ["B", 5]]);
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* ---
|
|
54
|
+
*
|
|
55
|
+
* @param iterable The iterable to aggregate.
|
|
56
|
+
*/
|
|
11
57
|
public constructor(iterable: Iterable<[K, T]>);
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Initializes a new instance of the {@link AggregatedIterator} class.
|
|
61
|
+
*
|
|
62
|
+
* ---
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* import { Random } from "@byloth/core";
|
|
67
|
+
*
|
|
68
|
+
* const iterator = new AggregatedIterator<string, number>({
|
|
69
|
+
* _index: 0,
|
|
70
|
+
* next: () =>
|
|
71
|
+
* {
|
|
72
|
+
* if (this._index >= 5) { return { done: true, value: undefined }; }
|
|
73
|
+
* this._index += 1;
|
|
74
|
+
*
|
|
75
|
+
* return { done: false, value: [Random.Choice(["A", "B", "C"]), (this._index + 1)] };
|
|
76
|
+
* }
|
|
77
|
+
* });
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
* ---
|
|
81
|
+
*
|
|
82
|
+
* @param iterator The iterator to aggregate.
|
|
83
|
+
*/
|
|
12
84
|
public constructor(iterator: Iterator<[K, T]>);
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Initializes a new instance of the {@link AggregatedIterator} class.
|
|
88
|
+
*
|
|
89
|
+
* ---
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* import { range, Random } from "@byloth/core";
|
|
94
|
+
*
|
|
95
|
+
* const iterator = new AggregatedIterator<string, number>(function* ()
|
|
96
|
+
* {
|
|
97
|
+
* for (const index of range(5))
|
|
98
|
+
* {
|
|
99
|
+
* yield [Random.Choice(["A", "B", "C"]), (index + 1)];
|
|
100
|
+
* }
|
|
101
|
+
* });
|
|
102
|
+
* ```
|
|
103
|
+
*
|
|
104
|
+
* ---
|
|
105
|
+
*
|
|
106
|
+
* @param generatorFn The generator function to aggregate.
|
|
107
|
+
*/
|
|
13
108
|
public constructor(generatorFn: GeneratorFunction<[K, T]>);
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Initializes a new instance of the {@link AggregatedIterator} class.
|
|
112
|
+
*
|
|
113
|
+
* ---
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```ts
|
|
117
|
+
* const iterator = new AggregatedIterator(keyedValues);
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* ---
|
|
121
|
+
*
|
|
122
|
+
* @param argument The iterable, iterator or generator function to aggregate.
|
|
123
|
+
*/
|
|
14
124
|
public constructor(argument: IteratorLike<[K, T]> | GeneratorFunction<[K, T]>);
|
|
15
125
|
public constructor(argument: IteratorLike<[K, T]> | GeneratorFunction<[K, T]>)
|
|
16
126
|
{
|
|
17
127
|
this._elements = new SmartIterator(argument);
|
|
18
128
|
}
|
|
19
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Determines whether all elements of each group of the iterator satisfy a given condition.
|
|
132
|
+
* See also {@link AggregatedIterator.some}.
|
|
133
|
+
* This method will consume the entire iterator in the process.
|
|
134
|
+
*
|
|
135
|
+
* It will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
136
|
+
* Once a single element of one group doesn't satisfy the condition,
|
|
137
|
+
* the result for the respective group will be `false`.
|
|
138
|
+
*
|
|
139
|
+
* Eventually, it will return a new {@link ReducedIterator}
|
|
140
|
+
* object that will contain all the boolean results for each group.
|
|
141
|
+
* If the iterator is infinite, the method will never return.
|
|
142
|
+
*
|
|
143
|
+
* ---
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```ts
|
|
147
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
148
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
149
|
+
* .every((key, value) => value >= 0);
|
|
150
|
+
*
|
|
151
|
+
* console.log(results.toObject()); // { odd: false, even: true }
|
|
152
|
+
* ```
|
|
153
|
+
*
|
|
154
|
+
* ---
|
|
155
|
+
*
|
|
156
|
+
* @param predicate The condition to check for each element of the iterator.
|
|
157
|
+
*
|
|
158
|
+
* @returns A new {@link ReducedIterator} containing the boolean results for each group.
|
|
159
|
+
*/
|
|
20
160
|
public every(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, boolean>
|
|
21
161
|
{
|
|
22
162
|
const values = new Map<K, [number, boolean]>();
|
|
@@ -35,6 +175,37 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
35
175
|
for (const [key, [_, result]] of values) { yield [key, result]; }
|
|
36
176
|
});
|
|
37
177
|
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Determines whether any elements of each group of the iterator satisfy a given condition.
|
|
181
|
+
* See also {@link AggregatedIterator.every}.
|
|
182
|
+
* This method will consume the entire iterator in the process.
|
|
183
|
+
*
|
|
184
|
+
* It will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
185
|
+
* Once a single element of one group satisfies the condition,
|
|
186
|
+
* the result for the respective group will be `true`.
|
|
187
|
+
*
|
|
188
|
+
* Eventually, it will return a new {@link ReducedIterator}
|
|
189
|
+
* object that will contain all the boolean results for each group.
|
|
190
|
+
* If the iterator is infinite, the method will never return.
|
|
191
|
+
*
|
|
192
|
+
* ---
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```ts
|
|
196
|
+
* const results = new SmartIterator<number>([-5, -4, -3, -2, -1, 0])
|
|
197
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
198
|
+
* .some((key, value) => value >= 0);
|
|
199
|
+
*
|
|
200
|
+
* console.log(results.toObject()); // { odd: false, even: true }
|
|
201
|
+
* ```
|
|
202
|
+
*
|
|
203
|
+
* ---
|
|
204
|
+
*
|
|
205
|
+
* @param predicate The condition to check for each element of the iterator.
|
|
206
|
+
*
|
|
207
|
+
* @returns A {@link ReducedIterator} containing the boolean results for each group.
|
|
208
|
+
*/
|
|
38
209
|
public some(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, boolean>
|
|
39
210
|
{
|
|
40
211
|
const values = new Map<K, [number, boolean]>();
|
|
@@ -54,8 +225,75 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
54
225
|
});
|
|
55
226
|
}
|
|
56
227
|
|
|
228
|
+
/**
|
|
229
|
+
* Filters the elements of the iterator using a given condition.
|
|
230
|
+
*
|
|
231
|
+
* This method will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
232
|
+
* If the condition is met, the element will be included in the new iterator.
|
|
233
|
+
*
|
|
234
|
+
* Since the iterator is lazy, the filtering process will
|
|
235
|
+
* be executed once the resulting iterator is materialized.
|
|
236
|
+
*
|
|
237
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
238
|
+
* This means that the original iterator won't be consumed until the
|
|
239
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
240
|
+
*
|
|
241
|
+
* ---
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```ts
|
|
245
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
246
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
247
|
+
* .filter((key, value) => value >= 0);
|
|
248
|
+
*
|
|
249
|
+
* console.log(results.toObject()); // { odd: [3, 5], even: [0, 2, 6, 8] }
|
|
250
|
+
* ```
|
|
251
|
+
*
|
|
252
|
+
* ---
|
|
253
|
+
*
|
|
254
|
+
* @param predicate The condition to check for each element of the iterator.
|
|
255
|
+
*
|
|
256
|
+
* @returns A new {@link AggregatedIterator} containing only the elements that satisfy the condition.
|
|
257
|
+
*/
|
|
57
258
|
public filter(predicate: KeyedIteratee<K, T, boolean>): AggregatedIterator<K, T>;
|
|
58
|
-
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Filters the elements of the iterator using a given condition.
|
|
262
|
+
*
|
|
263
|
+
* This method will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
264
|
+
* If the condition is met, the element will be included in the new iterator.
|
|
265
|
+
*
|
|
266
|
+
* Since the iterator is lazy, the filtering process will
|
|
267
|
+
* be executed once the resulting iterator is materialized.
|
|
268
|
+
*
|
|
269
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
270
|
+
* This means that the original iterator won't be consumed until the
|
|
271
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
272
|
+
*
|
|
273
|
+
* ---
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* ```ts
|
|
277
|
+
* const results = new SmartIterator<number | string>([-3, "-1", 0, "2", "3", 5, 6, "8"])
|
|
278
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
279
|
+
* .filter<number>((key, value) => typeof value === "number");
|
|
280
|
+
*
|
|
281
|
+
* console.log(results.toObject()); // { odd: [-3, 5], even: [0, 6] }
|
|
282
|
+
* ```
|
|
283
|
+
*
|
|
284
|
+
* ---
|
|
285
|
+
*
|
|
286
|
+
* @template S
|
|
287
|
+
* The type of the elements that satisfy the condition.
|
|
288
|
+
* This allows the type-system to infer the correct type of the new iterator.
|
|
289
|
+
*
|
|
290
|
+
* It must be a subtype of the original type of the elements.
|
|
291
|
+
*
|
|
292
|
+
* @param predicate The type guard condition to check for each element of the iterator.
|
|
293
|
+
*
|
|
294
|
+
* @returns A new {@link AggregatedIterator} containing only the elements that satisfy the condition.
|
|
295
|
+
*/
|
|
296
|
+
public filter<S extends T>(predicate: KeyedTypeGuardPredicate<K, T, S>): AggregatedIterator<K, S>;
|
|
59
297
|
public filter(predicate: KeyedIteratee<K, T, boolean>): AggregatedIterator<K, T>
|
|
60
298
|
{
|
|
61
299
|
const elements = this._elements;
|
|
@@ -63,17 +301,48 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
63
301
|
return new AggregatedIterator(function* ()
|
|
64
302
|
{
|
|
65
303
|
const indexes = new Map<K, number>();
|
|
66
|
-
|
|
67
304
|
for (const [key, element] of elements)
|
|
68
305
|
{
|
|
69
306
|
const index = indexes.get(key) ?? 0;
|
|
70
|
-
|
|
71
307
|
if (predicate(key, element, index)) { yield [key, element]; }
|
|
72
308
|
|
|
73
309
|
indexes.set(key, index + 1);
|
|
74
310
|
}
|
|
75
311
|
});
|
|
76
312
|
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Maps the elements of the iterator using a given transformation function.
|
|
316
|
+
*
|
|
317
|
+
* This method will iterate over all elements of the iterator applying the transformation function.
|
|
318
|
+
* The result of each transformation will be included in the new iterator.
|
|
319
|
+
*
|
|
320
|
+
* Since the iterator is lazy, the mapping process will
|
|
321
|
+
* be executed once the resulting iterator is materialized.
|
|
322
|
+
*
|
|
323
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
324
|
+
* This means that the original iterator won't be consumed until the
|
|
325
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
326
|
+
*
|
|
327
|
+
* ---
|
|
328
|
+
*
|
|
329
|
+
* @example
|
|
330
|
+
* ```ts
|
|
331
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
332
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
333
|
+
* .map((key, value) => Math.abs(value));
|
|
334
|
+
*
|
|
335
|
+
* console.log(results.toObject()); // { odd: [3, 1, 3, 5], even: [0, 2, 6, 8] }
|
|
336
|
+
* ```
|
|
337
|
+
*
|
|
338
|
+
* ---
|
|
339
|
+
*
|
|
340
|
+
* @template V The type of the elements after the transformation.
|
|
341
|
+
*
|
|
342
|
+
* @param iteratee The transformation function to apply to each element of the iterator.
|
|
343
|
+
*
|
|
344
|
+
* @returns A new {@link AggregatedIterator} containing the transformed elements.
|
|
345
|
+
*/
|
|
77
346
|
public map<V>(iteratee: KeyedIteratee<K, T, V>): AggregatedIterator<K, V>
|
|
78
347
|
{
|
|
79
348
|
const elements = this._elements;
|
|
@@ -81,20 +350,121 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
81
350
|
return new AggregatedIterator(function* ()
|
|
82
351
|
{
|
|
83
352
|
const indexes = new Map<K, number>();
|
|
84
|
-
|
|
85
353
|
for (const [key, element] of elements)
|
|
86
354
|
{
|
|
87
355
|
const index = indexes.get(key) ?? 0;
|
|
88
|
-
|
|
89
356
|
yield [key, iteratee(key, element, index)];
|
|
90
357
|
|
|
91
358
|
indexes.set(key, index + 1);
|
|
92
359
|
}
|
|
93
360
|
});
|
|
94
361
|
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Reduces the elements of the iterator using a given reducer function.
|
|
365
|
+
* This method will consume the entire iterator in the process.
|
|
366
|
+
*
|
|
367
|
+
* It will iterate over all elements of the iterator applying the reducer function.
|
|
368
|
+
* The result of each iteration will be passed as the accumulator to the next one.
|
|
369
|
+
*
|
|
370
|
+
* The first accumulator value will be the first element of the iterator.
|
|
371
|
+
* The last accumulator value will be the final result of the reduction.
|
|
372
|
+
*
|
|
373
|
+
* Eventually, it will return a new {@link ReducedIterator}
|
|
374
|
+
* object that will contain all the reduced results for each group.
|
|
375
|
+
* If the iterator is infinite, the method will never return.
|
|
376
|
+
*
|
|
377
|
+
* ---
|
|
378
|
+
*
|
|
379
|
+
* @example
|
|
380
|
+
* ```ts
|
|
381
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
382
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
383
|
+
* .reduce((key, accumulator, value) => accumulator + value);
|
|
384
|
+
*
|
|
385
|
+
* console.log(results.toObject()); // { odd: 4, even: 16 }
|
|
386
|
+
* ```
|
|
387
|
+
*
|
|
388
|
+
* ---
|
|
389
|
+
*
|
|
390
|
+
* @param reducer The reducer function to apply to each element of the iterator.
|
|
391
|
+
*
|
|
392
|
+
* @returns A new {@link ReducedIterator} containing the reduced results for each group.
|
|
393
|
+
*/
|
|
95
394
|
public reduce(reducer: KeyedReducer<K, T, T>): ReducedIterator<K, T>;
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Reduces the elements of the iterator using a given reducer function.
|
|
398
|
+
* This method will consume the entire iterator in the process.
|
|
399
|
+
*
|
|
400
|
+
* It will iterate over all elements of the iterator applying the reducer function.
|
|
401
|
+
* The result of each iteration will be passed as the accumulator to the next one.
|
|
402
|
+
*
|
|
403
|
+
* The first accumulator value will be the provided initial value.
|
|
404
|
+
* The last accumulator value will be the final result of the reduction.
|
|
405
|
+
*
|
|
406
|
+
* Eventually, it will return a new {@link ReducedIterator}
|
|
407
|
+
* object that will contain all the reduced results for each group.
|
|
408
|
+
* If the iterator is infinite, the method will never return.
|
|
409
|
+
*
|
|
410
|
+
* ---
|
|
411
|
+
*
|
|
412
|
+
* @example
|
|
413
|
+
* ```ts
|
|
414
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
415
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
416
|
+
* .reduce((key, accumulator, value) => accumulator + value, 0);
|
|
417
|
+
*
|
|
418
|
+
* console.log(results.toObject()); // { odd: 4, even: 16 }
|
|
419
|
+
* ```
|
|
420
|
+
*
|
|
421
|
+
* ---
|
|
422
|
+
*
|
|
423
|
+
* @template A The type of the accumulator value which will also be the type of the final result of the reduction.
|
|
424
|
+
*
|
|
425
|
+
* @param reducer The reducer function to apply to each element of the iterator.
|
|
426
|
+
* @param initialValue The initial value of the accumulator.
|
|
427
|
+
*
|
|
428
|
+
* @returns A new {@link ReducedIterator} containing the reduced results for each group.
|
|
429
|
+
*/
|
|
430
|
+
public reduce<A extends PropertyKey>(reducer: KeyedReducer<K, T, A>, initialValue: A): ReducedIterator<K, A>;
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Reduces the elements of the iterator using a given reducer function.
|
|
434
|
+
* This method will consume the entire iterator in the process.
|
|
435
|
+
*
|
|
436
|
+
* It will iterate over all elements of the iterator applying the reducer function.
|
|
437
|
+
* The result of each iteration will be passed as the accumulator to the next one.
|
|
438
|
+
*
|
|
439
|
+
* The first accumulator value will be the provided initial value by the given function.
|
|
440
|
+
* The last accumulator value will be the final result of the reduction.
|
|
441
|
+
*
|
|
442
|
+
* Eventually, it will return a new {@link ReducedIterator}
|
|
443
|
+
* object that will contain all the reduced results for each group.
|
|
444
|
+
* If the iterator is infinite, the method will never return.
|
|
445
|
+
*
|
|
446
|
+
* ---
|
|
447
|
+
*
|
|
448
|
+
* @example
|
|
449
|
+
* ```ts
|
|
450
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
451
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
452
|
+
* .reduce((key, { value }, currentValue) => ({ value: value + currentValue }), (key) => ({ value: 0 }));
|
|
453
|
+
*
|
|
454
|
+
* console.log(results.toObject()); // { odd: { value: 4 }, even: { value: 16 } }
|
|
455
|
+
* ```
|
|
456
|
+
*
|
|
457
|
+
* ---
|
|
458
|
+
*
|
|
459
|
+
* @template A The type of the accumulator value which will also be the type of the final result of the reduction.
|
|
460
|
+
*
|
|
461
|
+
* @param reducer The reducer function to apply to each element of the iterator.
|
|
462
|
+
* @param initialValue The function that provides the initial value for the accumulator.
|
|
463
|
+
*
|
|
464
|
+
* @returns A new {@link ReducedIterator} containing the reduced results for each group.
|
|
465
|
+
*/
|
|
96
466
|
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>
|
|
467
|
+
public reduce<A>(reducer: KeyedReducer<K, T, A>, initialValue?: A | ((key: K) => A)): ReducedIterator<K, A>
|
|
98
468
|
{
|
|
99
469
|
const values = new Map<K, [number, A]>();
|
|
100
470
|
|
|
@@ -107,7 +477,9 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
107
477
|
else if (initialValue !== undefined)
|
|
108
478
|
{
|
|
109
479
|
index = 0;
|
|
110
|
-
|
|
480
|
+
|
|
481
|
+
if (initialValue instanceof Function) { accumulator = initialValue(key); }
|
|
482
|
+
else { accumulator = initialValue; }
|
|
111
483
|
}
|
|
112
484
|
else
|
|
113
485
|
{
|
|
@@ -125,26 +497,94 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
125
497
|
});
|
|
126
498
|
}
|
|
127
499
|
|
|
128
|
-
|
|
500
|
+
/**
|
|
501
|
+
* Flattens the elements of the iterator using a given transformation function.
|
|
502
|
+
*
|
|
503
|
+
* This method will iterate over all elements of the iterator applying the transformation function.
|
|
504
|
+
* The result of each transformation will be included in the new iterator.
|
|
505
|
+
*
|
|
506
|
+
* Since the iterator is lazy, the flattening process will
|
|
507
|
+
* be executed once the resulting iterator is materialized.
|
|
508
|
+
*
|
|
509
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
510
|
+
* This means that the original iterator won't be consumed until the
|
|
511
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
512
|
+
*
|
|
513
|
+
* ---
|
|
514
|
+
*
|
|
515
|
+
* @example
|
|
516
|
+
* ```ts
|
|
517
|
+
* const results = new SmartIterator<number[]>([[-3, -1], 0, 2, 3, 5, [6, 8]])
|
|
518
|
+
* .groupBy((values) =>
|
|
519
|
+
* {
|
|
520
|
+
* const value = values instanceof Array ? values[0] : values;
|
|
521
|
+
* return value % 2 === 0 ? "even" : "odd";
|
|
522
|
+
* })
|
|
523
|
+
* .flatMap((key, values) => values);
|
|
524
|
+
*
|
|
525
|
+
* console.log(results.toObject()); // { odd: [-3, -1, 3, 5], even: [0, 2, 6, 8] }
|
|
526
|
+
* ```
|
|
527
|
+
*
|
|
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 AggregatedIterator} containing the transformed elements.
|
|
535
|
+
*/
|
|
536
|
+
public flatMap<V>(iteratee: KeyedIteratee<K, T, V | readonly V[]>): AggregatedIterator<K, V>
|
|
129
537
|
{
|
|
130
538
|
const elements = this._elements;
|
|
131
539
|
|
|
132
540
|
return new AggregatedIterator(function* ()
|
|
133
541
|
{
|
|
134
542
|
const indexes = new Map<K, number>();
|
|
135
|
-
|
|
136
543
|
for (const [key, element] of elements)
|
|
137
544
|
{
|
|
138
545
|
const index = indexes.get(key) ?? 0;
|
|
139
546
|
const values = iteratee(key, element, index);
|
|
140
547
|
|
|
141
|
-
|
|
548
|
+
if (values instanceof Array)
|
|
549
|
+
{
|
|
550
|
+
for (const value of values) { yield [key, value]; }
|
|
551
|
+
}
|
|
552
|
+
else { yield [key, values]; }
|
|
142
553
|
|
|
143
554
|
indexes.set(key, index + 1);
|
|
144
555
|
}
|
|
145
556
|
});
|
|
146
557
|
}
|
|
147
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 AggregatedIterator.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
|
+
* ---
|
|
572
|
+
*
|
|
573
|
+
* @example
|
|
574
|
+
* ```ts
|
|
575
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
576
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
577
|
+
* .drop(2);
|
|
578
|
+
*
|
|
579
|
+
* console.log(results.toObject()); // { odd: [3, 5], even: [6, 8] }
|
|
580
|
+
* ```
|
|
581
|
+
*
|
|
582
|
+
* ---
|
|
583
|
+
*
|
|
584
|
+
* @param count The number of elements to drop from the beginning of each group.
|
|
585
|
+
*
|
|
586
|
+
* @returns A new {@link AggregatedIterator} containing the remaining elements.
|
|
587
|
+
*/
|
|
148
588
|
public drop(count: number): AggregatedIterator<K, T>
|
|
149
589
|
{
|
|
150
590
|
const elements = this._elements;
|
|
@@ -152,7 +592,6 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
152
592
|
return new AggregatedIterator(function* ()
|
|
153
593
|
{
|
|
154
594
|
const indexes = new Map<K, number>();
|
|
155
|
-
|
|
156
595
|
for (const [key, element] of elements)
|
|
157
596
|
{
|
|
158
597
|
const index = indexes.get(key) ?? 0;
|
|
@@ -167,6 +606,36 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
167
606
|
}
|
|
168
607
|
});
|
|
169
608
|
}
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* Takes a given number of elements from the beginning of each group of the iterator.
|
|
612
|
+
* The elements will be included in the new iterator.
|
|
613
|
+
* See also {@link AggregatedIterator.drop}.
|
|
614
|
+
*
|
|
615
|
+
* Since the iterator is lazy, the taking process will
|
|
616
|
+
* be executed once the resulting iterator is materialized.
|
|
617
|
+
*
|
|
618
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
619
|
+
* This means that the original iterator won't be consumed until the
|
|
620
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
621
|
+
*
|
|
622
|
+
* ---
|
|
623
|
+
*
|
|
624
|
+
* @example
|
|
625
|
+
* ```ts
|
|
626
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
627
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
628
|
+
* .take(2);
|
|
629
|
+
*
|
|
630
|
+
* console.log(results.toObject()); // { odd: [-3, -1], even: [0, 2] }
|
|
631
|
+
* ```
|
|
632
|
+
*
|
|
633
|
+
* ---
|
|
634
|
+
*
|
|
635
|
+
* @param limit The number of elements to take from the beginning of each group.
|
|
636
|
+
*
|
|
637
|
+
* @returns A new {@link AggregatedIterator} containing the taken elements.
|
|
638
|
+
*/
|
|
170
639
|
public take(limit: number): AggregatedIterator<K, T>
|
|
171
640
|
{
|
|
172
641
|
const elements = this._elements;
|
|
@@ -174,12 +643,10 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
174
643
|
return new AggregatedIterator(function* ()
|
|
175
644
|
{
|
|
176
645
|
const indexes = new Map<K, number>();
|
|
177
|
-
|
|
178
646
|
for (const [key, element] of elements)
|
|
179
647
|
{
|
|
180
648
|
const index = indexes.get(key) ?? 0;
|
|
181
649
|
if (index >= limit) { continue; }
|
|
182
|
-
|
|
183
650
|
yield [key, element];
|
|
184
651
|
|
|
185
652
|
indexes.set(key, index + 1);
|
|
@@ -187,8 +654,73 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
187
654
|
});
|
|
188
655
|
}
|
|
189
656
|
|
|
657
|
+
/**
|
|
658
|
+
* Finds the first element of each group of the iterator that satisfies a given condition.
|
|
659
|
+
* This method will consume the entire iterator in the process.
|
|
660
|
+
*
|
|
661
|
+
* It will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
662
|
+
* Once the first element of one group satisfies the condition,
|
|
663
|
+
* the result for the respective group will be the element itself.
|
|
664
|
+
*
|
|
665
|
+
* Eventually, it will return a new {@link ReducedIterator}
|
|
666
|
+
* object that will contain the first element that satisfies the condition for each group.
|
|
667
|
+
* If the iterator is infinite, the method will never return.
|
|
668
|
+
*
|
|
669
|
+
* ---
|
|
670
|
+
*
|
|
671
|
+
* @example
|
|
672
|
+
* ```ts
|
|
673
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
674
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
675
|
+
* .find((key, value) => value > 0);
|
|
676
|
+
*
|
|
677
|
+
* console.log(results.toObject()); // { odd: 3, even: 2 }
|
|
678
|
+
* ```
|
|
679
|
+
*
|
|
680
|
+
* ---
|
|
681
|
+
*
|
|
682
|
+
* @param predicate The condition to check for each element of the iterator.
|
|
683
|
+
*
|
|
684
|
+
* @returns A new {@link ReducedIterator} containing the first element that satisfies the condition for each group.
|
|
685
|
+
*/
|
|
190
686
|
public find(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, T | undefined>;
|
|
191
|
-
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* Finds the first element of each group of the iterator that satisfies a given condition.
|
|
690
|
+
* This method will consume the entire iterator in the process.
|
|
691
|
+
*
|
|
692
|
+
* It will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
693
|
+
* Once the first element of one group satisfies the condition,
|
|
694
|
+
* the result for the respective group will be the element itself.
|
|
695
|
+
*
|
|
696
|
+
* Eventually, it will return a new {@link ReducedIterator}
|
|
697
|
+
* object that will contain the first element that satisfies the condition for each group.
|
|
698
|
+
* If the iterator is infinite, the method will never return.
|
|
699
|
+
*
|
|
700
|
+
* ---
|
|
701
|
+
*
|
|
702
|
+
* @example
|
|
703
|
+
* ```ts
|
|
704
|
+
* const results = new SmartIterator<number | string>([-3, "-1", 0, "2", "3", 5, 6, "8"])
|
|
705
|
+
* .groupBy((value) => Number(value) % 2 === 0 ? "even" : "odd")
|
|
706
|
+
* .find<number>((key, value) => typeof value === "number");
|
|
707
|
+
*
|
|
708
|
+
* console.log(results.toObject()); // { odd: -3, even: 0 }
|
|
709
|
+
* ```
|
|
710
|
+
*
|
|
711
|
+
* ---
|
|
712
|
+
*
|
|
713
|
+
* @template S
|
|
714
|
+
* The type of the elements that satisfy the condition.
|
|
715
|
+
* This allows the type-system to infer the correct type of the new iterator.
|
|
716
|
+
*
|
|
717
|
+
* It must be a subtype of the original type of the elements.
|
|
718
|
+
*
|
|
719
|
+
* @param predicate The type guard condition to check for each element of the iterator.
|
|
720
|
+
*
|
|
721
|
+
* @returns A new {@link ReducedIterator} containing the first element that satisfies the condition for each group.
|
|
722
|
+
*/
|
|
723
|
+
public find<S extends T>(predicate: KeyedTypeGuardPredicate<K, T, S>): ReducedIterator<K, S | undefined>;
|
|
192
724
|
public find(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, T | undefined>
|
|
193
725
|
{
|
|
194
726
|
const values = new Map<K, [number, T | undefined]>();
|
|
@@ -209,10 +741,63 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
209
741
|
});
|
|
210
742
|
}
|
|
211
743
|
|
|
744
|
+
/**
|
|
745
|
+
* Enumerates the elements of the iterator.
|
|
746
|
+
* Each element is paired with its index within the group in a new iterator.
|
|
747
|
+
*
|
|
748
|
+
* Since the iterator is lazy, the enumeration process will
|
|
749
|
+
* be executed once the resulting iterator is materialized.
|
|
750
|
+
*
|
|
751
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
752
|
+
* This means that the original iterator won't be consumed until the
|
|
753
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
754
|
+
*
|
|
755
|
+
* ---
|
|
756
|
+
*
|
|
757
|
+
* @example
|
|
758
|
+
* ```ts
|
|
759
|
+
* const results = new SmartIterator<number>([-3, 0, 2, -1, 3])
|
|
760
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
761
|
+
* .enumerate();
|
|
762
|
+
*
|
|
763
|
+
* console.log(results.toObject()); // { odd: [[0, -3], [1, -1], [2, 3]], even: [[0, 0], [1, 2]] }
|
|
764
|
+
* ```
|
|
765
|
+
*
|
|
766
|
+
* ---
|
|
767
|
+
*
|
|
768
|
+
* @returns A new {@link AggregatedIterator} containing the enumerated elements.
|
|
769
|
+
*/
|
|
212
770
|
public enumerate(): AggregatedIterator<K, [number, T]>
|
|
213
771
|
{
|
|
214
772
|
return this.map((_, value, index) => [index, value]);
|
|
215
773
|
}
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* Removes all duplicate elements from within each group of the iterator.
|
|
777
|
+
* The first occurrence of each element will be included in the new iterator.
|
|
778
|
+
*
|
|
779
|
+
* Since the iterator is lazy, the deduplication process will
|
|
780
|
+
* be executed once the resulting iterator is materialized.
|
|
781
|
+
*
|
|
782
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
783
|
+
* This means that the original iterator won't be consumed until the
|
|
784
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
785
|
+
*
|
|
786
|
+
* ---
|
|
787
|
+
*
|
|
788
|
+
* @example
|
|
789
|
+
* ```ts
|
|
790
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 6, -3, -1, 0, 5, 6, 8, 0, 2])
|
|
791
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
792
|
+
* .unique();
|
|
793
|
+
*
|
|
794
|
+
* console.log(results.toObject()); // { odd: [-3, -1, 3, 5], even: [0, 2, 6, 8] }
|
|
795
|
+
* ```
|
|
796
|
+
*
|
|
797
|
+
* ---
|
|
798
|
+
*
|
|
799
|
+
* @returns A new {@link AggregatedIterator} containing only the unique elements.
|
|
800
|
+
*/
|
|
216
801
|
public unique(): AggregatedIterator<K, T>
|
|
217
802
|
{
|
|
218
803
|
const elements = this._elements;
|
|
@@ -220,11 +805,9 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
220
805
|
return new AggregatedIterator(function* ()
|
|
221
806
|
{
|
|
222
807
|
const keys = new Map<K, Set<T>>();
|
|
223
|
-
|
|
224
808
|
for (const [key, element] of elements)
|
|
225
809
|
{
|
|
226
810
|
const values = keys.get(key) ?? new Set<T>();
|
|
227
|
-
|
|
228
811
|
if (values.has(element)) { continue; }
|
|
229
812
|
|
|
230
813
|
values.add(element);
|
|
@@ -235,6 +818,27 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
235
818
|
});
|
|
236
819
|
}
|
|
237
820
|
|
|
821
|
+
/**
|
|
822
|
+
* Counts the number of elements within each group of the iterator.
|
|
823
|
+
* This method will consume the entire iterator in the process.
|
|
824
|
+
*
|
|
825
|
+
* If the iterator is infinite, the method will never return.
|
|
826
|
+
*
|
|
827
|
+
* ---
|
|
828
|
+
*
|
|
829
|
+
* @example
|
|
830
|
+
* ```ts
|
|
831
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
832
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
833
|
+
* .count();
|
|
834
|
+
*
|
|
835
|
+
* console.log(results.toObject()); // { odd: 4, even: 4 }
|
|
836
|
+
* ```
|
|
837
|
+
*
|
|
838
|
+
* ---
|
|
839
|
+
*
|
|
840
|
+
* @returns A new {@link ReducedIterator} containing the number of elements for each group.
|
|
841
|
+
*/
|
|
238
842
|
public count(): ReducedIterator<K, number>
|
|
239
843
|
{
|
|
240
844
|
const counters = new Map<K, number>();
|
|
@@ -252,20 +856,116 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
252
856
|
});
|
|
253
857
|
}
|
|
254
858
|
|
|
859
|
+
/**
|
|
860
|
+
* Iterates over the elements of the iterator.
|
|
861
|
+
* The elements are passed to the given iteratee function along with their key and index within the group.
|
|
862
|
+
*
|
|
863
|
+
* This method will consume the entire iterator in the process.
|
|
864
|
+
* If the iterator is infinite, the method will never return.
|
|
865
|
+
*
|
|
866
|
+
* ---
|
|
867
|
+
*
|
|
868
|
+
* @example
|
|
869
|
+
* ```ts
|
|
870
|
+
* const aggregator = new SmartIterator<number>([-3, 0, 2, -1, 3])
|
|
871
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd");
|
|
872
|
+
*
|
|
873
|
+
* aggregator.forEach((key, value, index) =>
|
|
874
|
+
* {
|
|
875
|
+
* console.log(`${index}: ${value}`); // "0: -3", "0: 0", "1: 2", "1: -1", "2: 3"
|
|
876
|
+
* };
|
|
877
|
+
* ```
|
|
878
|
+
*
|
|
879
|
+
* ---
|
|
880
|
+
*
|
|
881
|
+
* @param iteratee The function to execute for each element of the iterator.
|
|
882
|
+
*/
|
|
255
883
|
public forEach(iteratee: KeyedIteratee<K, T>): void
|
|
256
884
|
{
|
|
257
885
|
const indexes = new Map<K, number>();
|
|
258
|
-
|
|
259
886
|
for (const [key, element] of this._elements)
|
|
260
887
|
{
|
|
261
888
|
const index = indexes.get(key) ?? 0;
|
|
262
|
-
|
|
263
889
|
iteratee(key, element, index);
|
|
264
890
|
|
|
265
891
|
indexes.set(key, index + 1);
|
|
266
892
|
}
|
|
267
893
|
}
|
|
268
894
|
|
|
895
|
+
/**
|
|
896
|
+
* Changes the key of each element on which the iterator is aggregated.
|
|
897
|
+
* The new key is determined by the given iteratee function.
|
|
898
|
+
*
|
|
899
|
+
* Since the iterator is lazy, the reorganization process will
|
|
900
|
+
* be executed once the resulting iterator is materialized.
|
|
901
|
+
*
|
|
902
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
903
|
+
* This means that the original iterator won't be consumed until the
|
|
904
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
905
|
+
*
|
|
906
|
+
* ---
|
|
907
|
+
*
|
|
908
|
+
* @example
|
|
909
|
+
* ```ts
|
|
910
|
+
* const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
911
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
912
|
+
* .map((key, value, index) => index % 2 === 0 ? value : -value)
|
|
913
|
+
* .reorganizeBy((key, value) => value >= 0 ? "+" : "-");
|
|
914
|
+
*
|
|
915
|
+
* console.log(results.toObject()); // { "+": [1, 0, 3, 6], "-": [-3, -2, -5, -8] }
|
|
916
|
+
* ```
|
|
917
|
+
*
|
|
918
|
+
* ---
|
|
919
|
+
*
|
|
920
|
+
* @template J The type of the new key.
|
|
921
|
+
*
|
|
922
|
+
* @param iteratee The function to determine the new key for each element of the iterator.
|
|
923
|
+
*
|
|
924
|
+
* @returns A new {@link AggregatedIterator} containing the elements reorganized by the new keys.
|
|
925
|
+
*/
|
|
926
|
+
public reorganizeBy<J extends PropertyKey>(iteratee: KeyedIteratee<K, T, J>): AggregatedIterator<J, T>
|
|
927
|
+
{
|
|
928
|
+
const elements = this._elements;
|
|
929
|
+
|
|
930
|
+
return new AggregatedIterator(function* ()
|
|
931
|
+
{
|
|
932
|
+
const indexes = new Map<K, number>();
|
|
933
|
+
for (const [key, element] of elements)
|
|
934
|
+
{
|
|
935
|
+
const index = indexes.get(key) ?? 0;
|
|
936
|
+
yield [iteratee(key, element, index), element];
|
|
937
|
+
|
|
938
|
+
indexes.set(key, index + 1);
|
|
939
|
+
}
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
/**
|
|
944
|
+
* An utility method that returns a new {@link SmartIterator}
|
|
945
|
+
* object containing all the keys of the iterator.
|
|
946
|
+
*
|
|
947
|
+
* Since the iterator is lazy, the keys will be extracted
|
|
948
|
+
* be executed once the resulting iterator is materialized.
|
|
949
|
+
*
|
|
950
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
951
|
+
* This means that the original iterator won't be consumed until the
|
|
952
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
953
|
+
*
|
|
954
|
+
* ---
|
|
955
|
+
*
|
|
956
|
+
* @example
|
|
957
|
+
* ```ts
|
|
958
|
+
* const keys = new SmartIterator([-3, Symbol(), "A", { }, null, [1 , 2, 3], false])
|
|
959
|
+
* .groupBy((value) => typeof value)
|
|
960
|
+
* .keys();
|
|
961
|
+
*
|
|
962
|
+
* console.log(keys.toArray()); // ["number", "symbol", "string", "object", "boolean"]
|
|
963
|
+
* ```
|
|
964
|
+
*
|
|
965
|
+
* ---
|
|
966
|
+
*
|
|
967
|
+
* @returns A new {@link SmartIterator} containing all the keys of the iterator.
|
|
968
|
+
*/
|
|
269
969
|
public keys(): SmartIterator<K>
|
|
270
970
|
{
|
|
271
971
|
const elements = this._elements;
|
|
@@ -273,7 +973,6 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
273
973
|
return new SmartIterator<K>(function* ()
|
|
274
974
|
{
|
|
275
975
|
const keys = new Set<K>();
|
|
276
|
-
|
|
277
976
|
for (const [key] of elements)
|
|
278
977
|
{
|
|
279
978
|
if (keys.has(key)) { continue; }
|
|
@@ -283,10 +982,65 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
283
982
|
}
|
|
284
983
|
});
|
|
285
984
|
}
|
|
286
|
-
|
|
985
|
+
|
|
986
|
+
/**
|
|
987
|
+
* An utility method that returns a new {@link SmartIterator}
|
|
988
|
+
* object containing all the entries of the iterator.
|
|
989
|
+
* Each entry is a tuple containing the key and the element.
|
|
990
|
+
*
|
|
991
|
+
* Since the iterator is lazy, the entries will be extracted
|
|
992
|
+
* be executed once the resulting iterator is materialized.
|
|
993
|
+
*
|
|
994
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
995
|
+
* This means that the original iterator won't be consumed until the
|
|
996
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
997
|
+
*
|
|
998
|
+
* ---
|
|
999
|
+
*
|
|
1000
|
+
* @example
|
|
1001
|
+
* ```ts
|
|
1002
|
+
* const entries = new SmartIterator<number>([-3, 0, 2, -1, 3])
|
|
1003
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
1004
|
+
* .entries();
|
|
1005
|
+
*
|
|
1006
|
+
* console.log(entries.toArray()); // [["odd", -3], ["even", 0], ["even", 2], ["odd", -1], ["odd", 3]]
|
|
1007
|
+
* ```
|
|
1008
|
+
*
|
|
1009
|
+
* ---
|
|
1010
|
+
*
|
|
1011
|
+
* @returns A new {@link SmartIterator} containing all the entries of the iterator.
|
|
1012
|
+
*/
|
|
1013
|
+
public entries(): SmartIterator<[K, T]>
|
|
287
1014
|
{
|
|
288
1015
|
return this._elements;
|
|
289
1016
|
}
|
|
1017
|
+
|
|
1018
|
+
/**
|
|
1019
|
+
* An utility method that returns a new {@link SmartIterator}
|
|
1020
|
+
* object containing all the values of the iterator.
|
|
1021
|
+
*
|
|
1022
|
+
* Since the iterator is lazy, the values will be extracted
|
|
1023
|
+
* be executed once the resulting iterator is materialized.
|
|
1024
|
+
*
|
|
1025
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
1026
|
+
* This means that the original iterator won't be consumed until the
|
|
1027
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
1028
|
+
*
|
|
1029
|
+
* ---
|
|
1030
|
+
*
|
|
1031
|
+
* @example
|
|
1032
|
+
* ```ts
|
|
1033
|
+
* const values = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
1034
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd")
|
|
1035
|
+
* .values();
|
|
1036
|
+
*
|
|
1037
|
+
* console.log(values.toArray()); // [-3, -1, 0, 2, 3, 5, 6, 8]
|
|
1038
|
+
* ```
|
|
1039
|
+
*
|
|
1040
|
+
* ---
|
|
1041
|
+
*
|
|
1042
|
+
* @returns A new {@link SmartIterator} containing all the values of the iterator.
|
|
1043
|
+
*/
|
|
290
1044
|
public values(): SmartIterator<T>
|
|
291
1045
|
{
|
|
292
1046
|
const elements = this._elements;
|
|
@@ -297,12 +1051,53 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
297
1051
|
});
|
|
298
1052
|
}
|
|
299
1053
|
|
|
1054
|
+
/**
|
|
1055
|
+
* Materializes the iterator into an array of arrays.
|
|
1056
|
+
* This method will consume the entire iterator in the process.
|
|
1057
|
+
*
|
|
1058
|
+
* If the iterator is infinite, the method will never return.
|
|
1059
|
+
*
|
|
1060
|
+
* ---
|
|
1061
|
+
*
|
|
1062
|
+
* @example
|
|
1063
|
+
* ```ts
|
|
1064
|
+
* const aggregator = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
1065
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd");
|
|
1066
|
+
*
|
|
1067
|
+
* console.log(aggregator.toArray()); // [[-3, -1, 3, 5], [0, 2, 6, 8]]
|
|
1068
|
+
* ```
|
|
1069
|
+
*
|
|
1070
|
+
* ---
|
|
1071
|
+
*
|
|
1072
|
+
* @returns An {@link Array} of arrays containing the elements of the iterator.
|
|
1073
|
+
*/
|
|
300
1074
|
public toArray(): T[][]
|
|
301
1075
|
{
|
|
302
1076
|
const map = this.toMap();
|
|
303
1077
|
|
|
304
1078
|
return Array.from(map.values());
|
|
305
1079
|
}
|
|
1080
|
+
|
|
1081
|
+
/**
|
|
1082
|
+
* Materializes the iterator into a map.
|
|
1083
|
+
* This method will consume the entire iterator in the process.
|
|
1084
|
+
*
|
|
1085
|
+
* If the iterator is infinite, the method will never return.
|
|
1086
|
+
*
|
|
1087
|
+
* ---
|
|
1088
|
+
*
|
|
1089
|
+
* @example
|
|
1090
|
+
* ```ts
|
|
1091
|
+
* const aggregator = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
1092
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd");
|
|
1093
|
+
*
|
|
1094
|
+
* console.log(aggregator.toMap()); // Map(2) { "odd" => [-3, -1, 3, 5], "even" => [0, 2, 6, 8] }
|
|
1095
|
+
* ```
|
|
1096
|
+
*
|
|
1097
|
+
* ---
|
|
1098
|
+
*
|
|
1099
|
+
* @returns A {@link Map} containing the elements of the iterator.
|
|
1100
|
+
*/
|
|
306
1101
|
public toMap(): Map<K, T[]>
|
|
307
1102
|
{
|
|
308
1103
|
const groups = new Map<K, T[]>();
|
|
@@ -317,6 +1112,27 @@ export default class AggregatedIterator<K extends PropertyKey, T>
|
|
|
317
1112
|
|
|
318
1113
|
return groups;
|
|
319
1114
|
}
|
|
1115
|
+
|
|
1116
|
+
/**
|
|
1117
|
+
* Materializes the iterator into an object.
|
|
1118
|
+
* This method will consume the entire iterator in the process.
|
|
1119
|
+
*
|
|
1120
|
+
* If the iterator is infinite, the method will never return.
|
|
1121
|
+
*
|
|
1122
|
+
* ---
|
|
1123
|
+
*
|
|
1124
|
+
* @example
|
|
1125
|
+
* ```ts
|
|
1126
|
+
* const aggregator = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])
|
|
1127
|
+
* .groupBy((value) => value % 2 === 0 ? "even" : "odd");
|
|
1128
|
+
*
|
|
1129
|
+
* console.log(aggregator.toObject()); // { odd: [-3, -1, 3, 5], even: [0, 2, 6, 8] }
|
|
1130
|
+
* ```
|
|
1131
|
+
*
|
|
1132
|
+
* ---
|
|
1133
|
+
*
|
|
1134
|
+
* @returns An {@link Object} containing the elements of the iterator.
|
|
1135
|
+
*/
|
|
320
1136
|
public toObject(): Record<K, T[]>
|
|
321
1137
|
{
|
|
322
1138
|
const groups = { } as Record<K, T[]>;
|