@byloth/core 1.2.0 → 1.3.0-rc.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 +408 -221
- 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 +4 -4
- package/src/index.ts +14 -3
- package/src/models/aggregators/_index.old.ts +384 -0
- package/src/models/aggregators/aggregated-iterator.ts +214 -0
- package/src/models/aggregators/index.ts +45 -0
- package/src/models/aggregators/reduced-iterator.ts +59 -0
- package/src/models/aggregators/types.ts +2 -0
- package/src/models/index.ts +14 -3
- package/src/models/smart-iterator.ts +56 -6
- package/src/utils/index.ts +5 -1
- package/src/utils/iterator.ts +19 -4
- package/src/utils/math.ts +3 -51
- package/src/utils/random.ts +39 -0
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
export function aggregate<V>(elements: Iterable<V>)
|
|
2
|
+
{
|
|
3
|
+
type Iteratee<K> = (element: V, index: number) => K;
|
|
4
|
+
|
|
5
|
+
function byKey<K extends string | number | symbol>(iteratee: Iteratee<K>)
|
|
6
|
+
{
|
|
7
|
+
function countToMap()
|
|
8
|
+
{
|
|
9
|
+
const counts = new Map<K, number>();
|
|
10
|
+
|
|
11
|
+
let index = 0;
|
|
12
|
+
for (const element of elements)
|
|
13
|
+
{
|
|
14
|
+
const key = iteratee(element, index);
|
|
15
|
+
|
|
16
|
+
if (counts.has(key))
|
|
17
|
+
{
|
|
18
|
+
counts.set(key, counts.get(key)! + 1);
|
|
19
|
+
}
|
|
20
|
+
else
|
|
21
|
+
{
|
|
22
|
+
counts.set(key, 1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
index += 1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return counts;
|
|
29
|
+
}
|
|
30
|
+
function countToDict()
|
|
31
|
+
{
|
|
32
|
+
const mapCounts = countToMap();
|
|
33
|
+
const dictCounts = { } as Record<K, number>;
|
|
34
|
+
|
|
35
|
+
for (const [key, _count] of mapCounts.entries())
|
|
36
|
+
{
|
|
37
|
+
dictCounts[key] = _count;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return dictCounts;
|
|
41
|
+
}
|
|
42
|
+
function count()
|
|
43
|
+
{
|
|
44
|
+
return Array.from(countToMap().values());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function groupToMap()
|
|
48
|
+
{
|
|
49
|
+
const groups = new Map<K, V[]>();
|
|
50
|
+
|
|
51
|
+
let index = 0;
|
|
52
|
+
for (const element of elements)
|
|
53
|
+
{
|
|
54
|
+
const key = iteratee(element, index);
|
|
55
|
+
|
|
56
|
+
if (groups.has(key))
|
|
57
|
+
{
|
|
58
|
+
groups.get(key)!
|
|
59
|
+
.push(element);
|
|
60
|
+
}
|
|
61
|
+
else
|
|
62
|
+
{
|
|
63
|
+
groups.set(key, [element]);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
index += 1;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return groups;
|
|
70
|
+
}
|
|
71
|
+
function groupToDict()
|
|
72
|
+
{
|
|
73
|
+
const mapGroups = groupToMap();
|
|
74
|
+
const dictGroup = { } as Record<K, V[]>;
|
|
75
|
+
|
|
76
|
+
for (const [key, _group] of mapGroups.entries())
|
|
77
|
+
{
|
|
78
|
+
dictGroup[key] = _group;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return dictGroup;
|
|
82
|
+
}
|
|
83
|
+
function group()
|
|
84
|
+
{
|
|
85
|
+
return Array.from(groupToMap().values());
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
type Reducer<R = V> = (key: K, group: R | undefined, element: V, index: number) => R;
|
|
89
|
+
|
|
90
|
+
function reduceToMap<R = V>(reducer: Reducer<R>, initialValue?: R | undefined)
|
|
91
|
+
{
|
|
92
|
+
const counts = new Map<K, number>();
|
|
93
|
+
const groups = new Map<K, R>();
|
|
94
|
+
|
|
95
|
+
let index = 0;
|
|
96
|
+
for (const element of elements)
|
|
97
|
+
{
|
|
98
|
+
let _count = 0;
|
|
99
|
+
let _group = initialValue;
|
|
100
|
+
|
|
101
|
+
const key = iteratee(element, index);
|
|
102
|
+
if (groups.has(key))
|
|
103
|
+
{
|
|
104
|
+
_count = counts.get(key)!;
|
|
105
|
+
_group = groups.get(key)!;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
_group = reducer(key, _group, element, _count);
|
|
109
|
+
|
|
110
|
+
counts.set(key, _count + 1);
|
|
111
|
+
groups.set(key, _group);
|
|
112
|
+
|
|
113
|
+
index += 1;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return groups;
|
|
117
|
+
}
|
|
118
|
+
function reduceToDict<R = V>(reducer: Reducer<R>, initialValue?: R | undefined)
|
|
119
|
+
{
|
|
120
|
+
const mapGroups = reduceToMap(reducer, initialValue);
|
|
121
|
+
const dictGroup = { } as Record<K, R>;
|
|
122
|
+
|
|
123
|
+
for (const [key, _group] of mapGroups.entries())
|
|
124
|
+
{
|
|
125
|
+
dictGroup[key] = _group;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return dictGroup;
|
|
129
|
+
}
|
|
130
|
+
function reduce<R = V>(reducer: Reducer<R>, initialValue?: R | undefined)
|
|
131
|
+
{
|
|
132
|
+
return Array.from(reduceToMap(reducer, initialValue).values());
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async function asyncReduceToMap<R = V>(reducer: Reducer<Promise<R>>, initialValue?: Promise<R> | undefined)
|
|
136
|
+
{
|
|
137
|
+
const awaitedGroups = new Map<K, R>();
|
|
138
|
+
const asyncGroups = reduceToMap(reducer, initialValue);
|
|
139
|
+
|
|
140
|
+
for (const [key, asyncGroup] of asyncGroups.entries())
|
|
141
|
+
{
|
|
142
|
+
awaitedGroups.set(key, await asyncGroup);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return awaitedGroups;
|
|
146
|
+
}
|
|
147
|
+
async function asyncReduceToDict<R = V>(reducer: Reducer<Promise<R>>, initialValue?: Promise<R> | undefined)
|
|
148
|
+
{
|
|
149
|
+
const mapGroups = reduceToMap(reducer, initialValue);
|
|
150
|
+
const dictGroup = { } as Record<K, R>;
|
|
151
|
+
|
|
152
|
+
for (const [key, _group] of mapGroups.entries())
|
|
153
|
+
{
|
|
154
|
+
dictGroup[key] = await _group;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return dictGroup;
|
|
158
|
+
}
|
|
159
|
+
function asyncReduce<R = V>(reducer: Reducer<Promise<R>>, initialValue?: Promise<R> | undefined)
|
|
160
|
+
{
|
|
161
|
+
return Promise.all(reduce(reducer, initialValue));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
count,
|
|
166
|
+
countToMap,
|
|
167
|
+
countToDict,
|
|
168
|
+
group,
|
|
169
|
+
groupToMap,
|
|
170
|
+
groupToDict,
|
|
171
|
+
reduce,
|
|
172
|
+
reduceToMap,
|
|
173
|
+
reduceToDict,
|
|
174
|
+
asyncReduce,
|
|
175
|
+
asyncReduceToMap,
|
|
176
|
+
asyncReduceToDict
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function byAsyncKey<K extends string | number | symbol>(iteratee: Iteratee<Promise<K>>)
|
|
180
|
+
{
|
|
181
|
+
async function countToMap()
|
|
182
|
+
{
|
|
183
|
+
const counts = new Map<K, number>();
|
|
184
|
+
|
|
185
|
+
let index = 0;
|
|
186
|
+
for (const element of elements)
|
|
187
|
+
{
|
|
188
|
+
const key = await iteratee(element, index);
|
|
189
|
+
|
|
190
|
+
if (counts.has(key))
|
|
191
|
+
{
|
|
192
|
+
counts.set(key, counts.get(key)! + 1);
|
|
193
|
+
}
|
|
194
|
+
else
|
|
195
|
+
{
|
|
196
|
+
counts.set(key, 1);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
index += 1;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return counts;
|
|
203
|
+
}
|
|
204
|
+
async function countToDict()
|
|
205
|
+
{
|
|
206
|
+
const mapCounts = await countToMap();
|
|
207
|
+
const dictCounts = { } as Record<K, number>;
|
|
208
|
+
|
|
209
|
+
for (const [key, _count] of mapCounts.entries())
|
|
210
|
+
{
|
|
211
|
+
dictCounts[key] = _count;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return dictCounts;
|
|
215
|
+
}
|
|
216
|
+
async function count()
|
|
217
|
+
{
|
|
218
|
+
const counts = await countToMap();
|
|
219
|
+
|
|
220
|
+
return Array.from(counts.values());
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async function groupToMap()
|
|
224
|
+
{
|
|
225
|
+
const groups = new Map<K, V[]>();
|
|
226
|
+
|
|
227
|
+
let index = 0;
|
|
228
|
+
for (const element of elements)
|
|
229
|
+
{
|
|
230
|
+
const key = await iteratee(element, index);
|
|
231
|
+
|
|
232
|
+
if (groups.has(key))
|
|
233
|
+
{
|
|
234
|
+
groups.get(key)!
|
|
235
|
+
.push(element);
|
|
236
|
+
}
|
|
237
|
+
else
|
|
238
|
+
{
|
|
239
|
+
groups.set(key, [element]);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
index += 1;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return groups;
|
|
246
|
+
}
|
|
247
|
+
async function groupToDict()
|
|
248
|
+
{
|
|
249
|
+
const mapGroups = await groupToMap();
|
|
250
|
+
const dictGroup = { } as Record<K, V[]>;
|
|
251
|
+
|
|
252
|
+
for (const [key, _group] of mapGroups.entries())
|
|
253
|
+
{
|
|
254
|
+
dictGroup[key] = _group;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return dictGroup;
|
|
258
|
+
}
|
|
259
|
+
async function group()
|
|
260
|
+
{
|
|
261
|
+
const groups = await groupToMap();
|
|
262
|
+
|
|
263
|
+
return Array.from(groups.values());
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
type Reducer<R = V> = (key: K, group: R | undefined, element: V, index: number) => R;
|
|
267
|
+
|
|
268
|
+
async function reduceToMap<R = V>(reducer: Reducer<R>, initialValue?: R | undefined)
|
|
269
|
+
{
|
|
270
|
+
const counts = new Map<K, number>();
|
|
271
|
+
const groups = new Map<K, R>();
|
|
272
|
+
|
|
273
|
+
let index = 0;
|
|
274
|
+
for (const element of elements)
|
|
275
|
+
{
|
|
276
|
+
let _count = 0;
|
|
277
|
+
let _group = initialValue;
|
|
278
|
+
|
|
279
|
+
const key = await iteratee(element, index);
|
|
280
|
+
if (groups.has(key))
|
|
281
|
+
{
|
|
282
|
+
_count = counts.get(key)!;
|
|
283
|
+
_group = groups.get(key)!;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
_group = reducer(key, _group, element, _count);
|
|
287
|
+
|
|
288
|
+
counts.set(key, _count + 1);
|
|
289
|
+
groups.set(key, _group);
|
|
290
|
+
|
|
291
|
+
index += 1;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return groups;
|
|
295
|
+
}
|
|
296
|
+
async function reduceToDict<R = V>(reducer: Reducer<R>, initialValue?: R | undefined)
|
|
297
|
+
{
|
|
298
|
+
const mapGroups = await reduceToMap(reducer, initialValue);
|
|
299
|
+
const dictGroup = { } as Record<K, R>;
|
|
300
|
+
|
|
301
|
+
for (const [key, _group] of mapGroups.entries())
|
|
302
|
+
{
|
|
303
|
+
dictGroup[key] = _group;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return dictGroup;
|
|
307
|
+
}
|
|
308
|
+
async function reduce<R = V>(reducer: Reducer<R>, initialValue?: R | undefined)
|
|
309
|
+
{
|
|
310
|
+
const groups = await reduceToMap(reducer, initialValue);
|
|
311
|
+
|
|
312
|
+
return Array.from(groups.values());
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
async function asyncReduceToMap<R = V>(reducer: Reducer<Promise<R>>, initialValue?: Promise<R> | undefined)
|
|
316
|
+
{
|
|
317
|
+
const awaitedGroups = new Map<K, R>();
|
|
318
|
+
const asyncGroups = await reduceToMap(reducer, initialValue);
|
|
319
|
+
|
|
320
|
+
for (const [key, asyncGroup] of asyncGroups.entries())
|
|
321
|
+
{
|
|
322
|
+
awaitedGroups.set(key, await asyncGroup);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return awaitedGroups;
|
|
326
|
+
}
|
|
327
|
+
async function asyncReduceToDict<R = V>(reducer: Reducer<Promise<R>>, initialValue?: Promise<R> | undefined)
|
|
328
|
+
{
|
|
329
|
+
const mapGroups = await reduceToMap(reducer, initialValue);
|
|
330
|
+
const dictGroup = { } as Record<K, R>;
|
|
331
|
+
|
|
332
|
+
for (const [key, _group] of mapGroups.entries())
|
|
333
|
+
{
|
|
334
|
+
dictGroup[key] = await _group;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return dictGroup;
|
|
338
|
+
}
|
|
339
|
+
async function asyncReduce<R = V>(reducer: Reducer<Promise<R>>, initialValue?: Promise<R> | undefined)
|
|
340
|
+
{
|
|
341
|
+
const groups = await reduce(reducer, initialValue);
|
|
342
|
+
|
|
343
|
+
return Promise.all(groups);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
return {
|
|
347
|
+
count,
|
|
348
|
+
countToMap,
|
|
349
|
+
countToDict,
|
|
350
|
+
group,
|
|
351
|
+
groupToMap,
|
|
352
|
+
groupToDict,
|
|
353
|
+
reduce,
|
|
354
|
+
reduceToMap,
|
|
355
|
+
reduceToDict,
|
|
356
|
+
asyncReduce,
|
|
357
|
+
asyncReduceToMap,
|
|
358
|
+
asyncReduceToDict
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
type Mapper<R> = (element: V, index: number) => R;
|
|
363
|
+
|
|
364
|
+
function map<R>(mapper: Mapper<R>)
|
|
365
|
+
{
|
|
366
|
+
const mapping: R[] = [];
|
|
367
|
+
|
|
368
|
+
let index = 0;
|
|
369
|
+
for (const element of elements)
|
|
370
|
+
{
|
|
371
|
+
mapping.push(mapper(element, index));
|
|
372
|
+
|
|
373
|
+
index += 1;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return mapping;
|
|
377
|
+
}
|
|
378
|
+
async function asyncMap<R>(mapper: Mapper<Promise<R>>)
|
|
379
|
+
{
|
|
380
|
+
return await Promise.all(map(mapper));
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
return { byKey, byAsyncKey, map, asyncMap };
|
|
384
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import ReducedIterator from "./reduced-iterator.js";
|
|
2
|
+
import SmartIterator from "../smart-iterator.js";
|
|
3
|
+
|
|
4
|
+
import type { KeyIteratee, KeyReducer } from "./types.js";
|
|
5
|
+
import type { GeneratorFunction } from "../../types.js";
|
|
6
|
+
|
|
7
|
+
export default class AggregatedIterator<T, K extends PropertyKey>
|
|
8
|
+
{
|
|
9
|
+
protected _elements: SmartIterator<[K, T]>;
|
|
10
|
+
|
|
11
|
+
public constructor(iterable: Iterable<[K, T]>);
|
|
12
|
+
public constructor(iterator: Iterator<[K, T]>);
|
|
13
|
+
public constructor(generatorFn: GeneratorFunction<[K, T]>);
|
|
14
|
+
public constructor(argument: Iterable<[K, T]> | Iterator<[K, T]> | GeneratorFunction<[K, T]>);
|
|
15
|
+
public constructor(argument: Iterable<[K, T]> | Iterator<[K, T]> | GeneratorFunction<[K, T]>)
|
|
16
|
+
{
|
|
17
|
+
this._elements = new SmartIterator(argument);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public every(predicate: KeyIteratee<T, K, boolean>): ReducedIterator<boolean, K>
|
|
21
|
+
{
|
|
22
|
+
const indexes = new Map<K, [number, boolean]>();
|
|
23
|
+
|
|
24
|
+
for (const [key, element] of this._elements)
|
|
25
|
+
{
|
|
26
|
+
const [index, result] = indexes.get(key) ?? [0, true];
|
|
27
|
+
|
|
28
|
+
if (!(result)) { continue; }
|
|
29
|
+
|
|
30
|
+
indexes.set(key, [index + 1, predicate(key, element, index)]);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return new ReducedIterator(function* ()
|
|
34
|
+
{
|
|
35
|
+
for (const [key, [_, result]] of indexes)
|
|
36
|
+
{
|
|
37
|
+
yield [key, result];
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
public some(predicate: KeyIteratee<T, K, boolean>): ReducedIterator<boolean, K>
|
|
42
|
+
{
|
|
43
|
+
const indexes = new Map<K, [number, boolean]>();
|
|
44
|
+
|
|
45
|
+
for (const [key, element] of this._elements)
|
|
46
|
+
{
|
|
47
|
+
const [index, result] = indexes.get(key) ?? [0, false];
|
|
48
|
+
|
|
49
|
+
if (result) { continue; }
|
|
50
|
+
|
|
51
|
+
indexes.set(key, [index + 1, predicate(key, element, index)]);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return new ReducedIterator(function* ()
|
|
55
|
+
{
|
|
56
|
+
for (const [key, [_, result]] of indexes)
|
|
57
|
+
{
|
|
58
|
+
yield [key, result];
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public filter(predicate: KeyIteratee<T, K, boolean>): AggregatedIterator<T, K>
|
|
64
|
+
{
|
|
65
|
+
const elements = this._elements;
|
|
66
|
+
|
|
67
|
+
return new AggregatedIterator(function* ()
|
|
68
|
+
{
|
|
69
|
+
const indexes = new Map<K, number>();
|
|
70
|
+
|
|
71
|
+
for (const [key, element] of elements)
|
|
72
|
+
{
|
|
73
|
+
const index = indexes.get(key) ?? 0;
|
|
74
|
+
|
|
75
|
+
indexes.set(key, index + 1);
|
|
76
|
+
|
|
77
|
+
if (predicate(key, element, index)) { yield [key, element]; }
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
public map<V>(iteratee: KeyIteratee<T, K, V>): AggregatedIterator<V, K>
|
|
82
|
+
{
|
|
83
|
+
const elements = this._elements;
|
|
84
|
+
|
|
85
|
+
return new AggregatedIterator(function* ()
|
|
86
|
+
{
|
|
87
|
+
const indexes = new Map<K, number>();
|
|
88
|
+
|
|
89
|
+
for (const [key, element] of elements)
|
|
90
|
+
{
|
|
91
|
+
const index = indexes.get(key) ?? 0;
|
|
92
|
+
|
|
93
|
+
indexes.set(key, index + 1);
|
|
94
|
+
|
|
95
|
+
yield [key, iteratee(key, element, index)];
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
public reduce<A>(reducer: KeyReducer<T, K, A>, initialValue?: A): ReducedIterator<A, K>
|
|
100
|
+
{
|
|
101
|
+
const accumulators = new Map<K, [number, A]>();
|
|
102
|
+
|
|
103
|
+
for (const [key, element] of this._elements)
|
|
104
|
+
{
|
|
105
|
+
let index: number;
|
|
106
|
+
let accumulator: A;
|
|
107
|
+
|
|
108
|
+
if (accumulators.has(key))
|
|
109
|
+
{
|
|
110
|
+
[index, accumulator] = accumulators.get(key)!;
|
|
111
|
+
|
|
112
|
+
index += 1;
|
|
113
|
+
}
|
|
114
|
+
else if (initialValue !== undefined)
|
|
115
|
+
{
|
|
116
|
+
index = 0;
|
|
117
|
+
accumulator = initialValue;
|
|
118
|
+
}
|
|
119
|
+
else
|
|
120
|
+
{
|
|
121
|
+
accumulators.set(key, [0, (element as unknown) as A]);
|
|
122
|
+
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
accumulator = reducer(key, accumulator, element, index);
|
|
127
|
+
|
|
128
|
+
accumulators.set(key, [index, accumulator]);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return new ReducedIterator(function* ()
|
|
132
|
+
{
|
|
133
|
+
for (const [key, [_, accumulator]] of accumulators)
|
|
134
|
+
{
|
|
135
|
+
yield [key, accumulator];
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public unique(): AggregatedIterator<T, K>
|
|
141
|
+
{
|
|
142
|
+
const elements = this._elements;
|
|
143
|
+
|
|
144
|
+
return new AggregatedIterator(function* ()
|
|
145
|
+
{
|
|
146
|
+
const keys = new Map<K, Set<T>>();
|
|
147
|
+
|
|
148
|
+
for (const [key, element] of elements)
|
|
149
|
+
{
|
|
150
|
+
const values = keys.get(key) ?? new Set<T>();
|
|
151
|
+
|
|
152
|
+
if (values.has(element)) { continue; }
|
|
153
|
+
|
|
154
|
+
values.add(element);
|
|
155
|
+
keys.set(key, values);
|
|
156
|
+
|
|
157
|
+
yield [key, element];
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public count(): ReducedIterator<number, K>
|
|
163
|
+
{
|
|
164
|
+
const counters = new Map<K, number>();
|
|
165
|
+
|
|
166
|
+
for (const [key] of this._elements)
|
|
167
|
+
{
|
|
168
|
+
const count = counters.get(key) ?? 0;
|
|
169
|
+
|
|
170
|
+
counters.set(key, count + 1);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return new ReducedIterator(function* ()
|
|
174
|
+
{
|
|
175
|
+
for (const [key, count] of counters)
|
|
176
|
+
{
|
|
177
|
+
yield [key, count];
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
public toArray(): T[][]
|
|
183
|
+
{
|
|
184
|
+
return Array.from(this.toMap().values());
|
|
185
|
+
}
|
|
186
|
+
public toMap(): Map<K, T[]>
|
|
187
|
+
{
|
|
188
|
+
const groups = new Map<K, T[]>();
|
|
189
|
+
|
|
190
|
+
for (const [key, element] of this._elements)
|
|
191
|
+
{
|
|
192
|
+
const value = groups.get(key) ?? [];
|
|
193
|
+
|
|
194
|
+
value.push(element);
|
|
195
|
+
groups.set(key, value);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return groups;
|
|
199
|
+
}
|
|
200
|
+
public toObject(): Record<K, T[]>
|
|
201
|
+
{
|
|
202
|
+
const groups = { } as Record<K, T[]>;
|
|
203
|
+
|
|
204
|
+
for (const [key, element] of this._elements)
|
|
205
|
+
{
|
|
206
|
+
const value = groups[key] ?? [];
|
|
207
|
+
|
|
208
|
+
value.push(element);
|
|
209
|
+
groups[key] = value;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return groups;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import AggregatedIterator from "./aggregated-iterator.js";
|
|
2
|
+
import ReducedIterator from "./reduced-iterator.js";
|
|
3
|
+
import SmartIterator from "../smart-iterator.js";
|
|
4
|
+
|
|
5
|
+
import type { GeneratorFunction, Iteratee } from "../../types.js";
|
|
6
|
+
|
|
7
|
+
export default class Aggregator<T>
|
|
8
|
+
{
|
|
9
|
+
protected _elements: SmartIterator<T>;
|
|
10
|
+
|
|
11
|
+
public constructor(iterable: Iterable<T>);
|
|
12
|
+
public constructor(iterator: Iterator<T>);
|
|
13
|
+
public constructor(generatorFn: GeneratorFunction<T>);
|
|
14
|
+
public constructor(argument: Iterable<T> | Iterator<T> | GeneratorFunction<T>);
|
|
15
|
+
public constructor(argument: Iterable<T> | Iterator<T> | GeneratorFunction<T>)
|
|
16
|
+
{
|
|
17
|
+
this._elements = new SmartIterator(argument);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public filter(predicate: Iteratee<T, boolean>): Aggregator<T>
|
|
21
|
+
{
|
|
22
|
+
return new Aggregator(this._elements.filter(predicate));
|
|
23
|
+
}
|
|
24
|
+
public map<V>(iteratee: Iteratee<T, V>): Aggregator<V>
|
|
25
|
+
{
|
|
26
|
+
return new Aggregator(this._elements.map(iteratee));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public unique(): Aggregator<T>
|
|
30
|
+
{
|
|
31
|
+
return new Aggregator(this._elements.unique());
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public byKey<K extends PropertyKey>(iteratee: Iteratee<T, K>): AggregatedIterator<T, K>
|
|
35
|
+
{
|
|
36
|
+
return new AggregatedIterator(this._elements.map((element, index) =>
|
|
37
|
+
{
|
|
38
|
+
const key = iteratee(element, index);
|
|
39
|
+
|
|
40
|
+
return [key, element];
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { AggregatedIterator, ReducedIterator };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import SmartIterator from "../smart-iterator.js";
|
|
2
|
+
|
|
3
|
+
import type { KeyIteratee } from "./types.js";
|
|
4
|
+
import type { GeneratorFunction } from "../../types.js";
|
|
5
|
+
|
|
6
|
+
export default class ReducedIterator<T, K extends PropertyKey>
|
|
7
|
+
{
|
|
8
|
+
protected _elements: SmartIterator<[K, T]>;
|
|
9
|
+
|
|
10
|
+
public constructor(iterable: Iterable<[K, T]>);
|
|
11
|
+
public constructor(iterator: Iterator<[K, T]>);
|
|
12
|
+
public constructor(generatorFn: GeneratorFunction<[K, T]>);
|
|
13
|
+
public constructor(argument: Iterable<[K, T]> | Iterator<[K, T]> | GeneratorFunction<[K, T]>);
|
|
14
|
+
public constructor(argument: Iterable<[K, T]> | Iterator<[K, T]> | GeneratorFunction<[K, T]>)
|
|
15
|
+
{
|
|
16
|
+
this._elements = new SmartIterator(argument);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public filter(predicate: KeyIteratee<T, K, boolean>): ReducedIterator<T, K>
|
|
20
|
+
{
|
|
21
|
+
const elements = this._elements;
|
|
22
|
+
|
|
23
|
+
return new ReducedIterator(function* ()
|
|
24
|
+
{
|
|
25
|
+
for (const [index, [key, element]] of elements.enumerate())
|
|
26
|
+
{
|
|
27
|
+
if (predicate(key, element, index))
|
|
28
|
+
{
|
|
29
|
+
yield [key, element];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
public map<V>(iteratee: KeyIteratee<T, K, V>): ReducedIterator<V, K>
|
|
35
|
+
{
|
|
36
|
+
const elements = this._elements;
|
|
37
|
+
|
|
38
|
+
return new ReducedIterator(function* ()
|
|
39
|
+
{
|
|
40
|
+
for (const [index, [key, element]] of elements.enumerate())
|
|
41
|
+
{
|
|
42
|
+
yield [key, iteratee(key, element, index)];
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public toArray(): T[]
|
|
48
|
+
{
|
|
49
|
+
return Array.from(this.toMap().values());
|
|
50
|
+
}
|
|
51
|
+
public toMap(): Map<K, T>
|
|
52
|
+
{
|
|
53
|
+
return new Map(this._elements.toArray());
|
|
54
|
+
}
|
|
55
|
+
public toObject(): Record<K, T>
|
|
56
|
+
{
|
|
57
|
+
return Object.fromEntries(this._elements.toArray()) as Record<K, T>;
|
|
58
|
+
}
|
|
59
|
+
}
|