scats 1.4.0-dev → 1.4.1-dev
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/abstract-map.d.ts +4 -4
- package/dist/abstract-map.js +12 -15
- package/dist/abstract-set.d.ts +2 -2
- package/dist/abstract-set.js +6 -9
- package/dist/array-iterable.d.ts +1 -1
- package/dist/array-iterable.js +22 -26
- package/dist/collection.d.ts +4 -4
- package/dist/collection.js +50 -71
- package/dist/either.d.ts +4 -4
- package/dist/either.js +31 -39
- package/dist/hashmap.d.ts +2 -2
- package/dist/hashmap.js +9 -12
- package/dist/hashset.d.ts +3 -3
- package/dist/hashset.js +6 -11
- package/dist/index.d.ts +8 -8
- package/dist/index.js +9 -13
- package/dist/mappable.js +1 -2
- package/dist/mutable/hashmap.d.ts +3 -3
- package/dist/mutable/hashmap.js +3 -8
- package/dist/mutable/hashset.d.ts +2 -2
- package/dist/mutable/hashset.js +3 -8
- package/dist/mutable.d.ts +3 -3
- package/dist/mutable.js +3 -9
- package/dist/option.d.ts +6 -6
- package/dist/option.js +34 -44
- package/dist/try.d.ts +3 -3
- package/dist/try.js +27 -37
- package/dist/util.d.ts +2 -2
- package/dist/util.js +41 -50
- package/package.json +1 -1
- package/.eslintrc.cjs +0 -44
- package/coverage/clover.xml +0 -937
- package/coverage/coverage-final.json +0 -15
- package/coverage/lcov-report/array-iterable.ts.html +0 -1709
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -79
- package/coverage/lcov-report/collection.ts.html +0 -1475
- package/coverage/lcov-report/either.ts.html +0 -1934
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/hashmap.ts.html +0 -527
- package/coverage/lcov-report/hashset.ts.html +0 -392
- package/coverage/lcov-report/index.html +0 -126
- package/coverage/lcov-report/index.ts.html +0 -101
- package/coverage/lcov-report/option.ts.html +0 -758
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -170
- package/coverage/lcov-report/src/abstract-map.ts.html +0 -317
- package/coverage/lcov-report/src/abstract-set.ts.html +0 -200
- package/coverage/lcov-report/src/array-iterable.ts.html +0 -1751
- package/coverage/lcov-report/src/collection.ts.html +0 -1778
- package/coverage/lcov-report/src/either.ts.html +0 -1934
- package/coverage/lcov-report/src/hashmap.ts.html +0 -428
- package/coverage/lcov-report/src/hashset.ts.html +0 -482
- package/coverage/lcov-report/src/index.html +0 -276
- package/coverage/lcov-report/src/index.ts.html +0 -110
- package/coverage/lcov-report/src/mutable/hashmap.ts.html +0 -821
- package/coverage/lcov-report/src/mutable/hashset.ts.html +0 -611
- package/coverage/lcov-report/src/mutable/index.html +0 -126
- package/coverage/lcov-report/src/mutable.ts.html +0 -89
- package/coverage/lcov-report/src/option.ts.html +0 -758
- package/coverage/lcov-report/src/try.ts.html +0 -923
- package/coverage/lcov-report/src/util.ts.html +0 -518
- package/coverage/lcov-report/try.ts.html +0 -923
- package/coverage/lcov-report/util.ts.html +0 -518
- package/coverage/lcov.info +0 -2223
- package/jest.config.js +0 -32
- package/src/abstract-map.ts +0 -79
- package/src/abstract-set.ts +0 -40
- package/src/array-iterable.ts +0 -557
- package/src/collection.ts +0 -619
- package/src/either.ts +0 -618
- package/src/hashmap.ts +0 -116
- package/src/hashset.ts +0 -134
- package/src/index.ts +0 -10
- package/src/mappable.ts +0 -8
- package/src/mutable/hashmap.ts +0 -247
- package/src/mutable/hashset.ts +0 -177
- package/src/mutable.ts +0 -3
- package/src/option.ts +0 -226
- package/src/try.ts +0 -281
- package/src/util.ts +0 -146
package/src/collection.ts
DELETED
|
@@ -1,619 +0,0 @@
|
|
|
1
|
-
import {Mappable} from './mappable';
|
|
2
|
-
import {HashMap, HashSet, Option} from './index';
|
|
3
|
-
import {Filterable} from './util';
|
|
4
|
-
import {ArrayIterable} from './array-iterable';
|
|
5
|
-
|
|
6
|
-
export abstract class ArrayBackedCollection<T, C extends ArrayIterable<T, any>> extends ArrayIterable<T, C> {
|
|
7
|
-
|
|
8
|
-
protected abstract readonly items: T[];
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
protected checkWithinBounds(lo: number, hi: number): void {
|
|
12
|
-
if (lo < 0) throw new Error(`$lo is out of bounds (min 0, max ${this.items.length - 1})`);
|
|
13
|
-
if (hi > this.size) throw new Error(`$lo is out of bounds (min 0, max ${this.items.length - 1})`);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
get reverse(): C {
|
|
17
|
-
return this.fromArray(this.items.reverse());
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
get toArray(): T[] {
|
|
21
|
-
return this.items;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
get(index: number): T {
|
|
25
|
-
this.checkWithinBounds(index, index + 1);
|
|
26
|
-
return this.items[index];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
get toSet(): HashSet<T> {
|
|
30
|
-
return HashSet.of(...this.items);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
indexOf(item: T): number {
|
|
35
|
-
return this.items.indexOf(item);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
get distinct(): C {
|
|
39
|
-
return this.fromArray(Array.from(new Set(this.items)));
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
distinctBy(key: (item: T) => string | number): C {
|
|
43
|
-
const keys = new Set();
|
|
44
|
-
const res: T[] = [];
|
|
45
|
-
this.foreach(item => {
|
|
46
|
-
const currentKey = key(item);
|
|
47
|
-
if (!keys.has(currentKey)) {
|
|
48
|
-
keys.add(currentKey);
|
|
49
|
-
res.push(item);
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
return this.fromArray(res);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
appended(item: T): C {
|
|
56
|
-
return this.fromArray(this.items.concat([item]));
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
appendedAll(other: Iterable<T>): C {
|
|
60
|
-
return this.fromArray(this.items.concat(...other));
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
prepended(item: T): C {
|
|
64
|
-
return this.fromArray([item].concat(this.items));
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
prependedAll(other: Iterable<T>): C {
|
|
68
|
-
return this.fromArray(Array.from(other).concat(this.items));
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
concat(other: Iterable<T>): C {
|
|
72
|
-
return this.appendedAll(other);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
slice(from: number, until: number): C {
|
|
76
|
-
return this.fromArray(this.items.slice(from, until));
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
sort(param: (a: T, b: T) => number): C {
|
|
80
|
-
return this.fromArray(this.items.slice(0).sort(param));
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
sortBy(fieldToNumber: (a: T) => number): C {
|
|
85
|
-
return this.sort(((a, b) => fieldToNumber(a) - fieldToNumber(b)));
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
get length(): number {
|
|
89
|
-
return this.size;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
export class Collection<T> extends ArrayBackedCollection<T, Collection<T>> implements Mappable<T>,
|
|
97
|
-
Filterable<T, Collection<T>> {
|
|
98
|
-
|
|
99
|
-
constructor(protected readonly items: T[]) {
|
|
100
|
-
super();
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
static empty = new Collection<any>([]);
|
|
104
|
-
|
|
105
|
-
protected fromArray(array: T[]): Collection<T> {
|
|
106
|
-
if (!array || array.length <= 0) {
|
|
107
|
-
return Nil;
|
|
108
|
-
} else {
|
|
109
|
-
return new Collection(array);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
static of<T>(...items: T[]): Collection<T> {
|
|
114
|
-
return new Collection<T>(items);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
static from<T>(elements: Iterable<T>): Collection<T> {
|
|
118
|
-
return new Collection<T>(Array.from(elements));
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
static fill<A>(len: number): (elem: (idx: number) => A) => Collection<A> {
|
|
122
|
-
return function(elem: (idx: number) => A): Collection<A> {
|
|
123
|
-
const res: A[] = new Array<A>(len);
|
|
124
|
-
for (let i = 0; i < len; i++) {
|
|
125
|
-
res[i] = elem(i);
|
|
126
|
-
}
|
|
127
|
-
return new Collection(res);
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
map<B>(f: (item: T) => B): Collection<B> {
|
|
132
|
-
return new Collection<B>(this.items.map(i => f(i)));
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
flatMap<B>(f: (item: T) => Collection<B>): Collection<B> {
|
|
136
|
-
//https://stackoverflow.com/questions/61740599/rangeerror-maximum-call-stack-size-exceeded-with-array-push
|
|
137
|
-
let res: B[] = [];
|
|
138
|
-
this.items.forEach(i => {
|
|
139
|
-
res = res.concat(f(i).items);
|
|
140
|
-
});
|
|
141
|
-
return new Collection<B>(res);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
flatMapOption<B>(f: (item: T) => Option<B>): Collection<B> {
|
|
145
|
-
const res: B[] = [];
|
|
146
|
-
this.items.forEach(i => {
|
|
147
|
-
f(i).foreach(v => {
|
|
148
|
-
res.push(v);
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
return new Collection<B>(res);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Maps each element of current collection to promise. Next element will be mapped once the current is resolved.
|
|
157
|
-
*
|
|
158
|
-
* This allows sequential processing of big amount of tasks in chunks:
|
|
159
|
-
* ```
|
|
160
|
-
* function processItem(i: number) {
|
|
161
|
-
* return Promise.resolve(i.toString(10));
|
|
162
|
-
* }
|
|
163
|
-
*
|
|
164
|
-
* const res: Collection<string> = (await Collection.fill<number>(100)(identity)
|
|
165
|
-
* .grouped(10)
|
|
166
|
-
* .mapPromise(async chunk =>
|
|
167
|
-
* new Collection(await Promise.all(chunk.map(i => processItem(i)).toArray))
|
|
168
|
-
* )).flatten<string>()
|
|
169
|
-
* ```
|
|
170
|
-
* @param f
|
|
171
|
-
*/
|
|
172
|
-
async mapPromise<B>(f: (v: T) => Promise<B>): Promise<Collection<B>> {
|
|
173
|
-
const res: B[] = [];
|
|
174
|
-
for (let i = 0; i < this.items.length; i++) {
|
|
175
|
-
res.push(await f(this.items[i]));
|
|
176
|
-
}
|
|
177
|
-
return new Collection<B>(res);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Maps each element of current collection to promise. All elements will be resolved concurrently.
|
|
182
|
-
* @param f
|
|
183
|
-
*/
|
|
184
|
-
async mapPromiseAll<B>(f: (v: T) => Promise<B>): Promise<Collection<B>> {
|
|
185
|
-
return new Collection<B>(await Promise.all(this.items.map(i => f(i))));
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Flat maps each element of current collection to promise. Next element will be mapped once the current is resolved.
|
|
190
|
-
*
|
|
191
|
-
* This allows sequential processing of big amount of tasks in chunks:
|
|
192
|
-
* ```
|
|
193
|
-
* function processItem(i: number) {
|
|
194
|
-
* return Promise.resolve(i.toString(10));
|
|
195
|
-
* }
|
|
196
|
-
*
|
|
197
|
-
* const res: Collection<string> = (await Collection
|
|
198
|
-
* .fill<number>(100)(identity)
|
|
199
|
-
* .grouped(10)
|
|
200
|
-
* .flatMapPromise(chunk => chunk.mapPromiseAll(i => processItem(i)));
|
|
201
|
-
* ```
|
|
202
|
-
* @param f
|
|
203
|
-
*/
|
|
204
|
-
async flatMapPromise<B>(f: (item: T) => Promise<Collection<B>>): Promise<Collection<B>> {
|
|
205
|
-
let res: B[] = [];
|
|
206
|
-
for (let i = 0; i < this.items.length; i++) {
|
|
207
|
-
const item = this.items[i];
|
|
208
|
-
res = res.concat((await f(item)).items);
|
|
209
|
-
}
|
|
210
|
-
return new Collection<B>(res);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Maps each element of current collection to promise. All elements will be resolved concurrently.
|
|
215
|
-
* @param f
|
|
216
|
-
*/
|
|
217
|
-
async flatMapPromiseAll<B>(f: (v: T) => Promise<Collection<B>>): Promise<Collection<B>> {
|
|
218
|
-
return (await this.mapPromiseAll(f)).flatten<B>();
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
flatten<B>(): Collection<B> {
|
|
223
|
-
const res: B[] = [];
|
|
224
|
-
this.items.forEach(i => {
|
|
225
|
-
if (i instanceof Collection) {
|
|
226
|
-
res.push(...i.items);
|
|
227
|
-
} else {
|
|
228
|
-
res.push(i as any as B);
|
|
229
|
-
}
|
|
230
|
-
});
|
|
231
|
-
return new Collection<B>(res);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
get toBuffer(): ArrayBuffer<T> {
|
|
235
|
-
return new ArrayBuffer(this.items);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
toMap<K, V>(mapper: (item: T) => [K, V]): HashMap<K, V> {
|
|
239
|
-
return HashMap.of(...this.map(mapper).toArray);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
/** Returns a $coll formed from this $coll and another iterable collection
|
|
244
|
-
* by combining corresponding elements in pairs.
|
|
245
|
-
* If one of the two collections is longer than the other, its remaining elements are ignored.
|
|
246
|
-
*
|
|
247
|
-
* @param that The iterable providing the second half of each result pair
|
|
248
|
-
* @tparam B the type of the second half of the returned pairs
|
|
249
|
-
* @return a new $coll containing pairs consisting of corresponding elements of this $coll and `that`.
|
|
250
|
-
* The length of the returned collection is the minimum of the lengths of this $coll and `that`.
|
|
251
|
-
*/
|
|
252
|
-
zip<B>(that: Collection<B>): Collection<[T, B]> {
|
|
253
|
-
const res: [T, B][] = [];
|
|
254
|
-
for (let i = 0; i < Math.min(this.size, that.size); i++) {
|
|
255
|
-
res.push([this.items[i], that.items[i]]);
|
|
256
|
-
}
|
|
257
|
-
return new Collection<[T, B]>(res);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/** Returns a $coll formed from this $coll and another iterable collection
|
|
261
|
-
* by combining corresponding elements in pairs.
|
|
262
|
-
* If one of the two collections is shorter than the other,
|
|
263
|
-
* placeholder elements are used to extend the shorter collection to the length of the longer.
|
|
264
|
-
*
|
|
265
|
-
* @param that the iterable providing the second half of each result pair
|
|
266
|
-
* @param thisElem the element to be used to fill up the result if this $coll is shorter than `that`.
|
|
267
|
-
* @param thatElem the element to be used to fill up the result if `that` is shorter than this $coll.
|
|
268
|
-
* @return a new collection of type `That` containing pairs consisting of
|
|
269
|
-
* corresponding elements of this $coll and `that`. The length
|
|
270
|
-
* of the returned collection is the maximum of the lengths of this $coll and `that`.
|
|
271
|
-
* If this $coll is shorter than `that`, `thisElem` values are used to pad the result.
|
|
272
|
-
* If `that` is shorter than this $coll, `thatElem` values are used to pad the result.
|
|
273
|
-
*/
|
|
274
|
-
zipAll<B>(that: Collection<B>, thisElem: T, thatElem: B): Collection<[T, B]> {
|
|
275
|
-
const res: [T, B][] = [];
|
|
276
|
-
for (let i = 0; i < Math.max(this.size, that.size); i++) {
|
|
277
|
-
res.push([
|
|
278
|
-
i < this.items.length ? this.items[i] : thisElem,
|
|
279
|
-
i < that.items.length ? that.items[i] : thatElem]);
|
|
280
|
-
}
|
|
281
|
-
return new Collection<[T, B]>(res);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
export const Nil = Collection.empty;
|
|
289
|
-
|
|
290
|
-
export class ArrayBuffer<T> extends ArrayBackedCollection<T, ArrayBuffer<T>> implements Mappable<T>,
|
|
291
|
-
Filterable<T, ArrayBuffer<T>>{
|
|
292
|
-
|
|
293
|
-
static get empty(): ArrayBuffer<any> {
|
|
294
|
-
return new ArrayBuffer<any>([]);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
constructor(protected readonly items: T[] = []) {
|
|
298
|
-
super();
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
static of<T>(...elements: T[]): ArrayBuffer<T> {
|
|
302
|
-
return new ArrayBuffer<T>(elements);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
static from<T>(elements: Iterable<T>): ArrayBuffer<T> {
|
|
306
|
-
return new ArrayBuffer<T>(Array.from(elements));
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
static fill<A>(len: number): (elem: (idx: number) => A) => ArrayBuffer<A> {
|
|
310
|
-
return function (elem: (idx: number) => A): ArrayBuffer<A> {
|
|
311
|
-
const res: A[] = new Array<A>(len);
|
|
312
|
-
for (let i = 0; i < len; i++) {
|
|
313
|
-
res[i] = elem(i);
|
|
314
|
-
}
|
|
315
|
-
return new ArrayBuffer(res);
|
|
316
|
-
};
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
protected fromArray(array: T[]): ArrayBuffer<T> {
|
|
320
|
-
if (!array || array.length <= 0) {
|
|
321
|
-
return new ArrayBuffer<T>([]);
|
|
322
|
-
} else {
|
|
323
|
-
return new ArrayBuffer(array);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
private normalized(n: number): number {
|
|
328
|
-
return Math.min(Math.max(n, 0), this.length);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
/** Replaces element at given index with a new value.
|
|
333
|
-
*
|
|
334
|
-
* @param index the index of the element to replace.
|
|
335
|
-
* @param element the new value.
|
|
336
|
-
* @throws Error if the index is not valid.
|
|
337
|
-
*/
|
|
338
|
-
update(index: number, element: T): void {
|
|
339
|
-
this.checkWithinBounds(index, index + 1);
|
|
340
|
-
this.items[index] = element;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
/** Replaces element at given index with a new value.
|
|
344
|
-
*
|
|
345
|
-
* @param index the index of the element to replace.
|
|
346
|
-
* @param element the new value.
|
|
347
|
-
* @throws Error if the index is not valid.
|
|
348
|
-
*/
|
|
349
|
-
set(index: number, element: T): void {
|
|
350
|
-
this.update(index, element);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* Clears the buffer's contents. After this operation, the
|
|
356
|
-
* buffer is empty.
|
|
357
|
-
*/
|
|
358
|
-
clear(): void {
|
|
359
|
-
this.items.length = 0;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
/**
|
|
364
|
-
* Appends the given elements to this buffer.
|
|
365
|
-
* @param element the element to append.
|
|
366
|
-
* @return the buffer itself
|
|
367
|
-
*/
|
|
368
|
-
append(element: T): this {
|
|
369
|
-
this.items.push(element);
|
|
370
|
-
return this;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
* Appends the elements contained in a iterable object to this buffer.
|
|
375
|
-
* @param elements the iterable object containing the elements to append.
|
|
376
|
-
* @return the buffer itself
|
|
377
|
-
*/
|
|
378
|
-
appendAll(elements: Iterable<T>): this {
|
|
379
|
-
this.items.push(...elements);
|
|
380
|
-
return this;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* Prepends a single element at the front of this ArrayBuffer.
|
|
385
|
-
*
|
|
386
|
-
* @param element the element to add.
|
|
387
|
-
* @return the buffer itself
|
|
388
|
-
*/
|
|
389
|
-
prepend(element: T): this {
|
|
390
|
-
this.items.unshift(element);
|
|
391
|
-
return this;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
prependAll(elements: Iterable<T>): this {
|
|
395
|
-
this.items.unshift(...elements);
|
|
396
|
-
return this;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
/**
|
|
400
|
-
* Inserts a new element at a given index into this buffer.
|
|
401
|
-
*
|
|
402
|
-
* @param idx the index where the new elements is inserted.
|
|
403
|
-
* @param element the element to insert.
|
|
404
|
-
* @throws Error if the index `idx` is not in the valid range
|
|
405
|
-
* `0 <= idx <= length`.
|
|
406
|
-
*/
|
|
407
|
-
insert(idx: number, element: T): void {
|
|
408
|
-
this.checkWithinBounds(idx, idx);
|
|
409
|
-
this.items.splice(idx, 0, element);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
/** Inserts new elements at the index `idx`. Opposed to method
|
|
413
|
-
* `update`, this method will not replace an element with a new
|
|
414
|
-
* one. Instead, it will insert a new element at index `idx`.
|
|
415
|
-
*
|
|
416
|
-
* @param idx the index where a new element will be inserted.
|
|
417
|
-
* @param elements the iterable object providing all elements to insert.
|
|
418
|
-
* @throws Error if `idx` is out of bounds.
|
|
419
|
-
*/
|
|
420
|
-
insertAll(idx: number, elements: Iterable<T>): void {
|
|
421
|
-
this.checkWithinBounds(idx, idx);
|
|
422
|
-
this.items.splice(idx, 0, ...elements);
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
/** Removes the element on a given index position.
|
|
426
|
-
*
|
|
427
|
-
* @param index the index which refers to the first element to remove.
|
|
428
|
-
* @param count the number of elements to remove.
|
|
429
|
-
* @throws Error if the index `idx` is not in the valid range
|
|
430
|
-
* `0 <= idx <= length - count` (with `count > 0`).
|
|
431
|
-
* @throws Error if `count < 0`.
|
|
432
|
-
*/
|
|
433
|
-
remove(index: number, count = 1): void {
|
|
434
|
-
if (count > 0) {
|
|
435
|
-
this.checkWithinBounds(index, index + 1);
|
|
436
|
-
this.items.splice(index, count);
|
|
437
|
-
} else if (count < 0) {
|
|
438
|
-
throw new Error('removing negative number of elements: ' + count);
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
/** Removes a single element from this buffer, at its first occurrence.
|
|
443
|
-
* If the buffer does not contain that element, it is unchanged.
|
|
444
|
-
*
|
|
445
|
-
* @param element the element to remove.
|
|
446
|
-
* @return the buffer itself
|
|
447
|
-
*/
|
|
448
|
-
subtractOne(element: T): this {
|
|
449
|
-
const i = this.items.indexOf(element);
|
|
450
|
-
if (i != -1) {
|
|
451
|
-
this.remove(i);
|
|
452
|
-
}
|
|
453
|
-
return this;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
/** Removes all elements produced by an iterator from this buffer.
|
|
457
|
-
*
|
|
458
|
-
* @param elements the iterator producing the elements to remove.
|
|
459
|
-
* @return the buffer itself
|
|
460
|
-
*/
|
|
461
|
-
subtractAll(elements: Iterable<T>): this {
|
|
462
|
-
if (elements === this || elements === this.items) {
|
|
463
|
-
const buf = new ArrayBuffer(Array.from(elements));
|
|
464
|
-
buf.foreach(e => this.subtractOne(e));
|
|
465
|
-
} else {
|
|
466
|
-
for (const element of elements) {
|
|
467
|
-
this.subtractOne(element);
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
return this;
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* returns same instance
|
|
476
|
-
* @param compareFn
|
|
477
|
-
* @return the buffer itself
|
|
478
|
-
*/
|
|
479
|
-
sort(compareFn?: (a: T, b: T) => number): this {
|
|
480
|
-
this.items.sort(compareFn);
|
|
481
|
-
return this;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
filterInPlace(p: (element: T) => boolean): this {
|
|
486
|
-
let i = 0, j = 0;
|
|
487
|
-
while (i < this.size) {
|
|
488
|
-
if (p(this.items[i])) {
|
|
489
|
-
if (i != j) {
|
|
490
|
-
this.items[j] = this.items[i];
|
|
491
|
-
}
|
|
492
|
-
j += 1;
|
|
493
|
-
}
|
|
494
|
-
i += 1;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
if (i == j) {
|
|
498
|
-
return this;
|
|
499
|
-
} else {
|
|
500
|
-
return this.takeInPlace(j);
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
dropInPlace(n: number): this {
|
|
506
|
-
this.remove(0, this.normalized(n));
|
|
507
|
-
return this;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
dropRightInPlace(n: number): this {
|
|
511
|
-
const norm = this.normalized(n);
|
|
512
|
-
this.remove(this.length - norm, norm);
|
|
513
|
-
return this;
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
takeInPlace(n: number): this {
|
|
517
|
-
const norm = this.normalized(n);
|
|
518
|
-
this.remove(norm, this.length - norm);
|
|
519
|
-
return this;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
takeRightInPlace(n: number): this {
|
|
523
|
-
this.remove(0, this.length - this.normalized(n));
|
|
524
|
-
return this;
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
sliceInPlace(start: number, end: number): this {
|
|
528
|
-
return this.takeInPlace(end).dropInPlace(start);
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
get toCollection(): Collection<T> {
|
|
532
|
-
return new Collection<T>(this.items.slice(0));
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
/** Builds a new ArrayBuffer by applying a function to all elements of this ArrayBuffer
|
|
537
|
-
* and using the elements of the resulting collections.
|
|
538
|
-
*
|
|
539
|
-
* For example:
|
|
540
|
-
*
|
|
541
|
-
* {{{
|
|
542
|
-
* getWords(lines: ArrayBuffer<string>): ArrayBuffer<string> {
|
|
543
|
-
* return lines.flatMap(line => ArrayBuffer.from(line.split("\\W+")))
|
|
544
|
-
* }
|
|
545
|
-
* }}}
|
|
546
|
-
*
|
|
547
|
-
*
|
|
548
|
-
* @param f the function to apply to each element.
|
|
549
|
-
* @tparam B the element type of the returned collection.
|
|
550
|
-
* @return a new ArrayBuffer resulting from applying the given collection-valued function
|
|
551
|
-
* `f` to each element of this $coll and concatenating the results.
|
|
552
|
-
*/
|
|
553
|
-
flatMap<B>(f: (item: T) => ArrayBuffer<B>): ArrayBuffer<B> {
|
|
554
|
-
//https://stackoverflow.com/questions/61740599/rangeerror-maximum-call-stack-size-exceeded-with-array-push
|
|
555
|
-
let res: B[] = [];
|
|
556
|
-
this.items.forEach(i => {
|
|
557
|
-
res = res.concat(f(i).items);
|
|
558
|
-
});
|
|
559
|
-
return new ArrayBuffer<B>(res);
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
flatMapOption<B>(f: (item: T) => Option<B>): ArrayBuffer<B> {
|
|
563
|
-
const res: B[] = [];
|
|
564
|
-
this.items.forEach(i => {
|
|
565
|
-
f(i).foreach(v => {
|
|
566
|
-
res.push(v);
|
|
567
|
-
});
|
|
568
|
-
});
|
|
569
|
-
return new ArrayBuffer<B>(res);
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
async flatMapPromise<B>(f: (item: T) => Promise<ArrayBuffer<B>>): Promise<ArrayBuffer<B>> {
|
|
574
|
-
//https://stackoverflow.com/questions/61740599/rangeerror-maximum-call-stack-size-exceeded-with-array-push
|
|
575
|
-
let res: B[] = [];
|
|
576
|
-
for (let i = 0; i < this.items.length; i++) {
|
|
577
|
-
const item = this.items[i];
|
|
578
|
-
res = res.concat((await f(item)).items);
|
|
579
|
-
}
|
|
580
|
-
return new ArrayBuffer<B>(res);
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
map<B>(f: (item: T) => B): ArrayBuffer<B> {
|
|
584
|
-
return new ArrayBuffer<B>(this.items.map(i => f(i)));
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
async mapPromise<B>(f: (v: T) => Promise<B>): Promise<ArrayBuffer<B>> {
|
|
588
|
-
const res: B[] = [];
|
|
589
|
-
for (let i = 0; i < this.items.length; i++) {
|
|
590
|
-
res.push(await f(this.items[i]));
|
|
591
|
-
}
|
|
592
|
-
return new ArrayBuffer<B>(res);
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
async mapPromiseAll<B>(f: (v: T) => Promise<B>): Promise<ArrayBuffer<B>> {
|
|
596
|
-
return new ArrayBuffer<B>(await Promise.all(this.items.map(i => f(i))));
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
async flatMapPromiseAll<B>(f: (v: T) => Promise<ArrayBuffer<B>>): Promise<ArrayBuffer<B>> {
|
|
600
|
-
return (await this.mapPromiseAll(f)).flatten<B>();
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
flatten<B>(): ArrayBuffer<B> {
|
|
604
|
-
const res: B[] = [];
|
|
605
|
-
this.items.forEach(i => {
|
|
606
|
-
if (i instanceof ArrayBuffer) {
|
|
607
|
-
res.push(...i.items);
|
|
608
|
-
} else {
|
|
609
|
-
res.push(i as any as B);
|
|
610
|
-
}
|
|
611
|
-
});
|
|
612
|
-
return new ArrayBuffer<B>(res);
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
toMap<K, V>(mapper: (item: T) => [K, V]): HashMap<K, V> {
|
|
616
|
-
return HashMap.of(...this.map(mapper).toArray);
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
}
|