@develia/commons 0.3.12 → 0.3.13
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/index.cjs.js.map +1 -1
- package/dist/index.esm.js.map +1 -1
- package/package.json +3 -2
- package/src/cache-dictionary.ts +78 -0
- package/src/from.ts +526 -0
- package/src/functions.ts +247 -0
- package/src/index.ts +11 -0
- package/src/lazy.ts +32 -0
- package/src/pair.ts +19 -0
- package/src/timer.ts +65 -0
- package/src/timespan.ts +217 -0
- package/src/types.ts +14 -0
package/src/from.ts
ADDED
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
import {Consumer, EqualityComparer, UnaryFunction, Predicate, Provider} from "./types";
|
|
2
|
+
import {toPairs} from "./functions";
|
|
3
|
+
import Pair from "./pair";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export default function from<T>(source: Iterable<T> | Provider<Iterable<T>>): From<T> | From<Pair<any, any>> {
|
|
7
|
+
if (source == null)
|
|
8
|
+
throw "Source is null.";
|
|
9
|
+
if (typeof source === 'function')
|
|
10
|
+
return From.fn<T>(source);
|
|
11
|
+
if (typeof source[Symbol.iterator] === 'function') {
|
|
12
|
+
return From.iterable<T>(source);
|
|
13
|
+
} else if (typeof source === 'object') {
|
|
14
|
+
return From.object(source)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
throw "Invalid source.";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class From<T> implements Iterable<T> {
|
|
21
|
+
|
|
22
|
+
public static object(obj: any): From<Pair<any, any>> {
|
|
23
|
+
return new From<Pair<any, any>>(function () {
|
|
24
|
+
return toPairs(obj);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private static _shallowEqual(obj1: any, obj2: any): boolean {
|
|
29
|
+
const keys1 = Object.keys(obj1);
|
|
30
|
+
const keys2 = Object.keys(obj2);
|
|
31
|
+
|
|
32
|
+
if (keys1.length !== keys2.length) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
for (let key of keys1) {
|
|
37
|
+
if (obj1[key] !== obj2[key]) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private readonly _fn: Provider<Iterable<T>>
|
|
46
|
+
|
|
47
|
+
protected constructor(fn: Provider<Iterable<T>>) {
|
|
48
|
+
this._fn = fn;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public static fn<T>(callable: Provider<Iterable<T>>): From<T> {
|
|
52
|
+
return new From<T>(callable);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
public collect(): From<T> {
|
|
56
|
+
const cache = Array.from(this);
|
|
57
|
+
return From.iterable(cache);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public static iterable<T>(iterable: Iterable<T>): From<T> {
|
|
61
|
+
return From.fn<T>(function* () {
|
|
62
|
+
for (const item of iterable) {
|
|
63
|
+
yield item;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
public map<R>(mapper: UnaryFunction<T, R>): From<R> {
|
|
69
|
+
const self = this;
|
|
70
|
+
return From.fn<R>(function* () {
|
|
71
|
+
for (let item of self) {
|
|
72
|
+
yield mapper(item);
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
* [Symbol.iterator](): Iterator<T> {
|
|
78
|
+
yield* this._fn()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
public all(predicate: Predicate<T>): boolean {
|
|
83
|
+
for (let item of this._fn()) {
|
|
84
|
+
if (!predicate(item)) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public any(predicate: Predicate<T>): boolean {
|
|
92
|
+
for (let item of this) {
|
|
93
|
+
if (predicate(item)) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
public filter(predicate: Predicate<T>): From<T> {
|
|
101
|
+
const self = this;
|
|
102
|
+
return From.fn<T>(function* () {
|
|
103
|
+
for (let item of self) {
|
|
104
|
+
if (predicate(item)) {
|
|
105
|
+
yield item;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public contains(value: T): boolean {
|
|
112
|
+
for (let item of this) {
|
|
113
|
+
if (item === value) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
// noinspection LoopStatementThatDoesntLoopJS
|
|
122
|
+
public first(predicate?: Predicate<T>): T | undefined {
|
|
123
|
+
|
|
124
|
+
if (predicate) {
|
|
125
|
+
for (let item of this) {
|
|
126
|
+
if (!predicate || predicate(item)) {
|
|
127
|
+
return item;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
// noinspection LoopStatementThatDoesntLoopJS
|
|
132
|
+
for (let item of this) {
|
|
133
|
+
return item;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public append(item: T): From<T> {
|
|
141
|
+
const self = this;
|
|
142
|
+
return From.fn<T>(function* () {
|
|
143
|
+
for (let element of self) {
|
|
144
|
+
yield element;
|
|
145
|
+
}
|
|
146
|
+
yield item;
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
public prepend(item: T): From<T> {
|
|
151
|
+
const self = this;
|
|
152
|
+
return From.fn<T>(function* () {
|
|
153
|
+
yield item;
|
|
154
|
+
for (let element of self) {
|
|
155
|
+
yield element;
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
public at(index: number): T | undefined {
|
|
161
|
+
let idx = 0;
|
|
162
|
+
for (let item of this) {
|
|
163
|
+
if (idx++ === index) {
|
|
164
|
+
return item;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
public last(predicate?: Predicate<T>): T | undefined {
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
let last: T | undefined = undefined;
|
|
174
|
+
|
|
175
|
+
if (predicate)
|
|
176
|
+
for (let item of this) {
|
|
177
|
+
if (!predicate || predicate(item)) {
|
|
178
|
+
last = item;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
for (let item of this) {
|
|
183
|
+
last = item;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return last;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
public mapMany<R>(mapper: UnaryFunction<T, Iterable<R>>): From<R> {
|
|
190
|
+
const self = this;
|
|
191
|
+
return From.fn(function* () {
|
|
192
|
+
for (const item of self) {
|
|
193
|
+
const subitems = mapper(item)
|
|
194
|
+
for (const subitem of subitems) {
|
|
195
|
+
yield subitem;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
})
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
public flatten(): From<any> {
|
|
202
|
+
const self = this;
|
|
203
|
+
return From.fn<T>(function* () {
|
|
204
|
+
for (let item of self) {
|
|
205
|
+
let temp = <Iterable<any>>item;
|
|
206
|
+
for (let subitem of temp) {
|
|
207
|
+
yield subitem
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
public sum(mapper?: UnaryFunction<T, number>): number {
|
|
214
|
+
let total = 0;
|
|
215
|
+
|
|
216
|
+
if (mapper)
|
|
217
|
+
for (let item of this) {
|
|
218
|
+
total += mapper(item);
|
|
219
|
+
}
|
|
220
|
+
else
|
|
221
|
+
for (let item of this) {
|
|
222
|
+
total += item as number;
|
|
223
|
+
}
|
|
224
|
+
return total;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
public avg(mapper?: UnaryFunction<T, number>): number {
|
|
228
|
+
let total = 0;
|
|
229
|
+
let count = 0;
|
|
230
|
+
|
|
231
|
+
if (mapper)
|
|
232
|
+
for (let item of this) {
|
|
233
|
+
total += mapper(item);
|
|
234
|
+
count++;
|
|
235
|
+
}
|
|
236
|
+
else
|
|
237
|
+
for (let item of this) {
|
|
238
|
+
total += item as number;
|
|
239
|
+
count++;
|
|
240
|
+
}
|
|
241
|
+
return count > 0 ? total / count : 0;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
public max(mapper: UnaryFunction<T, number>): number {
|
|
245
|
+
let max = -Infinity;
|
|
246
|
+
for (let item of this) {
|
|
247
|
+
let value = mapper(item);
|
|
248
|
+
max = value > max ? value : max;
|
|
249
|
+
}
|
|
250
|
+
return max;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
public min(mapper: UnaryFunction<T, number>): number {
|
|
254
|
+
let min = Infinity;
|
|
255
|
+
for (let item of this) {
|
|
256
|
+
let value = mapper(item);
|
|
257
|
+
min = value < min ? value : min;
|
|
258
|
+
}
|
|
259
|
+
return min;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
public maxBy(mapper: UnaryFunction<T, number>): T | undefined {
|
|
263
|
+
let max = -Infinity;
|
|
264
|
+
let maxItem: T | undefined;
|
|
265
|
+
for (let item of this) {
|
|
266
|
+
let value = mapper(item);
|
|
267
|
+
if (value > max) {
|
|
268
|
+
max = value;
|
|
269
|
+
maxItem = item;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return maxItem;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
public minBy(mapper: UnaryFunction<T, number>): T | undefined {
|
|
276
|
+
let min = Infinity;
|
|
277
|
+
let minItem: T | undefined;
|
|
278
|
+
for (let item of this) {
|
|
279
|
+
let value = mapper(item);
|
|
280
|
+
if (value < min) {
|
|
281
|
+
min = value;
|
|
282
|
+
minItem = item;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return minItem;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
public orderBy<R>(mapper: UnaryFunction<T, R>): From<T> {
|
|
289
|
+
const array = Array.from(this._fn());
|
|
290
|
+
array.sort((a, b) => {
|
|
291
|
+
const aValue = mapper(a);
|
|
292
|
+
const bValue = mapper(b);
|
|
293
|
+
return aValue > bValue ? 1 : aValue < bValue ? -1 : 0;
|
|
294
|
+
});
|
|
295
|
+
return From.iterable(array);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
public groupBy<TKey>(keySelector: UnaryFunction<T, TKey>, equalityComparer?: EqualityComparer<TKey>): From<Grouping<TKey, T>> {
|
|
299
|
+
|
|
300
|
+
equalityComparer = (equalityComparer == null ? From._shallowEqual : equalityComparer);
|
|
301
|
+
const self = this;
|
|
302
|
+
|
|
303
|
+
return From.fn<Grouping<TKey, T>>(function* () {
|
|
304
|
+
const groups: Array<[TKey, T[]]> = [];
|
|
305
|
+
for (let item of self) {
|
|
306
|
+
const key = keySelector(item);
|
|
307
|
+
let found = false;
|
|
308
|
+
for (let [entryKey, group] of groups) {
|
|
309
|
+
if (equalityComparer(key, entryKey)) {
|
|
310
|
+
group.push(item);
|
|
311
|
+
found = true;
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (!found) {
|
|
316
|
+
groups.push([key, [item]]);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
yield* groups.map(([key, values]) => new Grouping<TKey, T>(key, values));
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
public head(n: number): From<T> {
|
|
324
|
+
|
|
325
|
+
const self = this;
|
|
326
|
+
return From.fn<T>(function* () {
|
|
327
|
+
let count = 0;
|
|
328
|
+
for (let item of self) {
|
|
329
|
+
if (count++ < n) {
|
|
330
|
+
yield item;
|
|
331
|
+
} else {
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
public tail(n: number): From<T> {
|
|
339
|
+
|
|
340
|
+
const self = this;
|
|
341
|
+
return From.fn<T>(function* () {
|
|
342
|
+
let buffer = [];
|
|
343
|
+
for (let item of self) {
|
|
344
|
+
buffer.push(item);
|
|
345
|
+
if (buffer.length > n) {
|
|
346
|
+
buffer.shift();
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
yield* buffer;
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
public forEach(action: Consumer<T>): void {
|
|
354
|
+
for (let item of this) {
|
|
355
|
+
action(item);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
public toArray(): T[] {
|
|
360
|
+
return Array.from(this);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
public instancesOf(type: string): From<T> {
|
|
365
|
+
return this.filter(item => typeof item === type);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
public allInstanceOf(type: new (...args: any[]) => any): boolean {
|
|
369
|
+
for (let item of this) {
|
|
370
|
+
if (!(item instanceof type)) {
|
|
371
|
+
return false;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return true;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
public distinct(eq_comparer?: EqualityComparer<T>): From<T> {
|
|
378
|
+
|
|
379
|
+
if (eq_comparer == null)
|
|
380
|
+
eq_comparer = From._shallowEqual;
|
|
381
|
+
|
|
382
|
+
const self = this;
|
|
383
|
+
return From.fn<T>(function* () {
|
|
384
|
+
|
|
385
|
+
const included = [];
|
|
386
|
+
|
|
387
|
+
for (let item of self) {
|
|
388
|
+
if (!From.iterable(included).any(x => eq_comparer(x, item))) {
|
|
389
|
+
included.push(item);
|
|
390
|
+
yield item;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
public insert(item: T, index: number): From<T> {
|
|
397
|
+
|
|
398
|
+
const self = this;
|
|
399
|
+
return From.fn<T>(function* () {
|
|
400
|
+
let i = 0;
|
|
401
|
+
let inserted = false;
|
|
402
|
+
for (let existingItem of self) {
|
|
403
|
+
if (i === index) {
|
|
404
|
+
yield item;
|
|
405
|
+
inserted = true;
|
|
406
|
+
}
|
|
407
|
+
yield existingItem;
|
|
408
|
+
i++;
|
|
409
|
+
}
|
|
410
|
+
if (!inserted) {
|
|
411
|
+
yield item;
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
public skip(n: number): From<T> {
|
|
417
|
+
const self = this;
|
|
418
|
+
return From.fn<T>(function* () {
|
|
419
|
+
let i = 0;
|
|
420
|
+
for (let item of self) {
|
|
421
|
+
if (i >= n) {
|
|
422
|
+
yield item;
|
|
423
|
+
}
|
|
424
|
+
i++;
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
public union(other: Iterable<T>): From<T> {
|
|
431
|
+
const self = this;
|
|
432
|
+
return From.fn<T>(function* () {
|
|
433
|
+
yield* self;
|
|
434
|
+
yield* other;
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
public innerJoin<T2, R, R2>(other: Iterable<T2>, thisKeySelector: UnaryFunction<T, R>, otherKeySelector: UnaryFunction<T2, R>, resultSelector: (thisItem: T, otherItem: T2) => R2): From<R2> {
|
|
439
|
+
|
|
440
|
+
const self = this;
|
|
441
|
+
return From.fn<R2>(() => {
|
|
442
|
+
const otherByKey = new Map<R, T2>();
|
|
443
|
+
for (let item of other) {
|
|
444
|
+
otherByKey.set(otherKeySelector(item), item);
|
|
445
|
+
}
|
|
446
|
+
return Array.from(self)
|
|
447
|
+
.filter(item => otherByKey.has(thisKeySelector(item)))
|
|
448
|
+
.map(item => resultSelector(item, otherByKey.get(thisKeySelector(item))!));
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
public leftJoin<U, K, R>(other: Iterable<U>, thisKeySelector: UnaryFunction<T, K>, otherKeySelector: UnaryFunction<U, K>, resultSelector: (thisItem: T, otherItem: U | undefined) => R): From<R> {
|
|
453
|
+
|
|
454
|
+
const self = this;
|
|
455
|
+
return From.fn<R>(() => {
|
|
456
|
+
const otherByKey = new Map<K, U>();
|
|
457
|
+
for (let item of other) {
|
|
458
|
+
otherByKey.set(otherKeySelector(item), item);
|
|
459
|
+
}
|
|
460
|
+
return Array.from(self).map(item => resultSelector(item, otherByKey.get(thisKeySelector(item))));
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
public leftGroupJoin<U, K, R>(other: Iterable<U>, thisKeySelector: UnaryFunction<T, K>, otherKeySelector: UnaryFunction<U, K>, resultSelector: (thisItem: T, otherItems: Array<U>) => R): From<R> {
|
|
466
|
+
|
|
467
|
+
const self = this;
|
|
468
|
+
return From.fn<R>(() => {
|
|
469
|
+
const otherByKeys = new Map<K, Array<U>>();
|
|
470
|
+
for (let item of other) {
|
|
471
|
+
const key = otherKeySelector(item);
|
|
472
|
+
if (!otherByKeys.has(key)) {
|
|
473
|
+
otherByKeys.set(key, []);
|
|
474
|
+
}
|
|
475
|
+
otherByKeys.get(key)!.push(item);
|
|
476
|
+
}
|
|
477
|
+
return Array.from(self).map(item => resultSelector(item, otherByKeys.get(thisKeySelector(item)) || []));
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
public rightGroupJoin<U, K, R>(other: Iterable<U>, thisKeySelector: UnaryFunction<T, K>, otherKeySelector: UnaryFunction<U, K>, resultSelector: (thisItems: Array<T>, otherItem: U) => R): From<R> {
|
|
482
|
+
|
|
483
|
+
const self = this;
|
|
484
|
+
return From.fn<R>(() => {
|
|
485
|
+
const thisByKeys = new Map<K, Array<T>>();
|
|
486
|
+
for (let item of self) {
|
|
487
|
+
const key = thisKeySelector(item);
|
|
488
|
+
if (!thisByKeys.has(key)) {
|
|
489
|
+
thisByKeys.set(key, []);
|
|
490
|
+
}
|
|
491
|
+
thisByKeys.get(key)!.push(item);
|
|
492
|
+
}
|
|
493
|
+
return Array.from(other).map(item => resultSelector(thisByKeys.get(otherKeySelector(item)) || [], item));
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
public rightJoin<U, K, R>(other: Iterable<U>, thisKeySelector: UnaryFunction<T, K>, otherKeySelector: UnaryFunction<U, K>, resultSelector: (thisItem: T | undefined, otherItem: U) => R): From<R> {
|
|
499
|
+
|
|
500
|
+
const self = this;
|
|
501
|
+
return From.fn<R>(() => {
|
|
502
|
+
const thisByKey = new Map<K, T>();
|
|
503
|
+
for (let item of self) {
|
|
504
|
+
thisByKey.set(thisKeySelector(item), item);
|
|
505
|
+
}
|
|
506
|
+
return Array.from(other).map(item => resultSelector(thisByKey.get(otherKeySelector(item)), item));
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
export class Grouping<TKey, T> extends From<T> {
|
|
513
|
+
|
|
514
|
+
private readonly _key: TKey;
|
|
515
|
+
|
|
516
|
+
public get key(): TKey {
|
|
517
|
+
return this._key;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
public constructor(key: TKey, values: Array<T>) {
|
|
521
|
+
super(() => values);
|
|
522
|
+
this._key = key;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
}
|