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/jest.config.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
const config = {
|
|
3
|
-
preset: 'ts-jest',
|
|
4
|
-
testEnvironment: 'node',
|
|
5
|
-
rootDir: '.',
|
|
6
|
-
roots: ['test'],
|
|
7
|
-
collectCoverageFrom: ["src/**/*.ts"],
|
|
8
|
-
reporters: ['default'],
|
|
9
|
-
coverageThreshold: {
|
|
10
|
-
global: {
|
|
11
|
-
branches: 10,
|
|
12
|
-
functions: 50,
|
|
13
|
-
lines: 50,
|
|
14
|
-
statements: 50
|
|
15
|
-
}
|
|
16
|
-
},
|
|
17
|
-
extensionsToTreatAsEsm: ['.ts'],
|
|
18
|
-
moduleNameMapper: {
|
|
19
|
-
'^(\\.{1,2}/.*)\\.js$': '$1',
|
|
20
|
-
},
|
|
21
|
-
transform: {
|
|
22
|
-
// '^.+\\.[tj]sx?$' to process ts,js,tsx,jsx with `ts-jest`
|
|
23
|
-
// '^.+\\.m?[tj]sx?$' to process ts,js,tsx,jsx,mts,mjs,mtsx,mjsx with `ts-jest`
|
|
24
|
-
'^.+\\.tsx?$': [
|
|
25
|
-
'ts-jest',
|
|
26
|
-
{
|
|
27
|
-
useESM: true,
|
|
28
|
-
},
|
|
29
|
-
],
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
export default config;
|
package/src/abstract-map.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import {ArrayIterable} from './array-iterable';
|
|
2
|
-
import {option, Option} from './option';
|
|
3
|
-
import {HashSet} from './hashset';
|
|
4
|
-
import {Collection} from './collection';
|
|
5
|
-
|
|
6
|
-
export type Tuple2<K, V> = [K, V];
|
|
7
|
-
|
|
8
|
-
export abstract class AbstractMap<K, V, S extends AbstractMap<K, V, any>> extends ArrayIterable<Tuple2<K, V>, S> {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
protected constructor(protected readonly map: Map<K, V>) {
|
|
12
|
-
super();
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
get size(): number {
|
|
16
|
-
return this.map.size;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
get isEmpty(): boolean {
|
|
20
|
-
return this.map.size <= 0;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
get(key: K): Option<V> {
|
|
24
|
-
return option(this.map.get(key));
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
getOrElse(key: K, defaultValue: () => V): V {
|
|
28
|
-
return this.get(key).getOrElse(defaultValue);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
getOrElseValue(key: K, defaultValue: V): V {
|
|
32
|
-
return this.get(key).getOrElseValue(defaultValue);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
get keySet(): HashSet<K> {
|
|
36
|
-
return HashSet.of(...Array.from(this.map.keys()));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
get keyIterator(): IterableIterator<K> {
|
|
40
|
-
return this.map.keys();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
get keys(): Collection<K> {
|
|
44
|
-
return new Collection(Array.from(this.map.keys()));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
get values(): Collection<V> {
|
|
48
|
-
return new Collection(Array.from(this.map.values()));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
get valueIterator(): IterableIterator<V> {
|
|
52
|
-
return this.map.values();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
get entries(): Collection<Tuple2<K, V>> {
|
|
56
|
-
return new Collection(Array.from(this.map.entries()));
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
get entriesIterator(): IterableIterator<Tuple2<K, V>> {
|
|
60
|
-
return this.map.entries();
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
containsKey(key: K): boolean {
|
|
64
|
-
return this.map.has(key);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
get toCollection(): Collection<Tuple2<K, V>> {
|
|
68
|
-
return new Collection<Tuple2<K, V>>(Array.from(this.map.entries()));
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
get toMap(): Map<K, V> {
|
|
72
|
-
return this.map;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
get toArray(): Array<Tuple2<K, V>> {
|
|
76
|
-
return Array.from(this.map.entries());
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
}
|
package/src/abstract-set.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import {ArrayIterable} from './array-iterable';
|
|
2
|
-
import {ArrayBuffer, Collection} from './collection';
|
|
3
|
-
|
|
4
|
-
export abstract class AbstractSet<T, S extends AbstractSet<T, any>> extends ArrayIterable<T, S> {
|
|
5
|
-
|
|
6
|
-
protected constructor(protected readonly items: Set<T>) {
|
|
7
|
-
super();
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
contains(item: T): boolean {
|
|
12
|
-
return this.items.has(item);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
get toArray(): Array<T> {
|
|
16
|
-
return Array.from(this.items.keys());
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
get toCollection(): Collection<T> {
|
|
20
|
-
return new Collection(Array.from(this.items.keys()));
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
get toSet(): Set<T> {
|
|
24
|
-
return new Set(this.items);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
get isEmpty(): boolean {
|
|
28
|
-
return this.items.size <= 0;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
get size(): number {
|
|
32
|
-
return this.items.size;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
get toBuffer(): ArrayBuffer<T> {
|
|
36
|
-
return new ArrayBuffer(Array.from(this.items.keys()));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
package/src/array-iterable.ts
DELETED
|
@@ -1,557 +0,0 @@
|
|
|
1
|
-
import {Collection, HashMap, none, option, Option, some} from './index';
|
|
2
|
-
|
|
3
|
-
export abstract class ArrayIterable<T, C extends ArrayIterable<T, any>> implements Iterable<T> {
|
|
4
|
-
|
|
5
|
-
[Symbol.iterator](): Iterator<T, T | undefined, undefined> {
|
|
6
|
-
let i = 0;
|
|
7
|
-
const items = this.toArray;
|
|
8
|
-
return {
|
|
9
|
-
next() {
|
|
10
|
-
if (i < items.length) {
|
|
11
|
-
const value = items[i];
|
|
12
|
-
i = i + 1;
|
|
13
|
-
return {
|
|
14
|
-
value: value,
|
|
15
|
-
done: false
|
|
16
|
-
};
|
|
17
|
-
} else {
|
|
18
|
-
return {
|
|
19
|
-
value: undefined,
|
|
20
|
-
done: true
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
abstract get toArray(): Array<T>;
|
|
28
|
-
|
|
29
|
-
protected abstract fromArray(array: T[]): C;
|
|
30
|
-
|
|
31
|
-
foreach<U>(job: (item: T) => U): void {
|
|
32
|
-
this.toArray.forEach(x => job(x));
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
contains(item: T): boolean {
|
|
36
|
-
return this.toArray.indexOf(item) >= 0;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
forall(p: (item: T) => boolean): boolean {
|
|
40
|
-
return this.toArray.every(i => p(i));
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
exists(p: (item: T) => boolean): boolean {
|
|
44
|
-
return this.toArray.find(i => p(i)) !== undefined;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
find(p: (item: T) => boolean): Option<T> {
|
|
48
|
-
return option(this.toArray.find(i => p(i)));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
count(p: (item: T) => boolean): number {
|
|
52
|
-
let res = 0;
|
|
53
|
-
this.toArray.forEach(i => {
|
|
54
|
-
if (p(i)) {
|
|
55
|
-
res++;
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
return res;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Tests whether the collection is empty.
|
|
64
|
-
* @return `true` if the collection contains no elements, `false` otherwise.
|
|
65
|
-
*/
|
|
66
|
-
get isEmpty(): boolean {
|
|
67
|
-
return this.size <= 0;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Tests whether the collection is not empty.
|
|
72
|
-
* @return `true` if the collection contains at least one element, `false` otherwise.
|
|
73
|
-
*/
|
|
74
|
-
get nonEmpty(): boolean {
|
|
75
|
-
return !this.isEmpty;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* The size of this collection.
|
|
80
|
-
* @return the number of elements in this collection.
|
|
81
|
-
*/
|
|
82
|
-
get size(): number {
|
|
83
|
-
return this.toArray.length;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
reduce(op: (i1: T, i2: T) => T): T {
|
|
88
|
-
return this.reduceLeft(op);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
reduceOption(op: (i1: T, i2: T) => T): Option<T> {
|
|
92
|
-
return this.reduceLeftOption(op);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
get headOption(): Option<T> {
|
|
96
|
-
return this.isEmpty ? none : some(this.head);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
get head(): T {
|
|
100
|
-
if (this.isEmpty) {
|
|
101
|
-
throw new Error('head on empty collection');
|
|
102
|
-
} else {
|
|
103
|
-
return this.toArray[0];
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
get lastOption(): Option<T> {
|
|
108
|
-
return this.isEmpty ? none : some(this.last);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
get last(): T {
|
|
113
|
-
if (this.isEmpty) {
|
|
114
|
-
throw new Error('empty.last');
|
|
115
|
-
} else {
|
|
116
|
-
return this.toArray[this.size - 1];
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
reduceLeft(op: (i1: T, i2: T) => T): T {
|
|
121
|
-
if (this.isEmpty) {
|
|
122
|
-
throw new Error('empty.reduceLeft');
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const array = this.toArray;
|
|
126
|
-
let acc = array[0];
|
|
127
|
-
if (array.length > 1) {
|
|
128
|
-
for (let i = 1; i < array.length; i++) {
|
|
129
|
-
acc = op(acc, array[i]);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
return acc;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
reduceLeftOption(op: (i1: T, i2: T) => T): Option<T> {
|
|
136
|
-
return this.isEmpty ? none : some(this.reduceLeft(op));
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
foldRight<B>(initial: B): (op: (next: T, acc: B) => B) => B {
|
|
140
|
-
return (op: (next: T, acc: B) => B) => {
|
|
141
|
-
return new Collection(this.toArray)
|
|
142
|
-
.reverse
|
|
143
|
-
.foldLeft(initial)((a, n) => op(n, a));
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
reduceRight(op: (i1: T, i2: T) => T): T {
|
|
148
|
-
if (this.isEmpty) {
|
|
149
|
-
throw new Error('empty.reduceRight');
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
let acc = this.last;
|
|
153
|
-
const array = this.toArray.reverse();
|
|
154
|
-
if (array.length > 1) {
|
|
155
|
-
for (let i = 1; i < array.length; i++) {
|
|
156
|
-
acc = op(acc, array[i]);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
return acc;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
reduceRightOption(op: (i1: T, i2: T) => T): Option<T> {
|
|
163
|
-
return this.isEmpty ? none : some(this.reduceRight(op));
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
foldLeft<B>(initial: B): (op: (acc: B, next: T) => B) => B {
|
|
168
|
-
return (op: (acc: B, next: T) => B) => {
|
|
169
|
-
return this.toArray.reduce((a, n) => op(a, n), initial);
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
fold<B>(initial: B): (op: (acc: B, next: T) => B) => B {
|
|
174
|
-
return this.foldLeft(initial);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
groupBy<K>(field: (item: T) => K): HashMap<K, Collection<T>> {
|
|
179
|
-
return this.foldLeft<HashMap<K, Collection<T>>>(HashMap.empty)((acc, next) => {
|
|
180
|
-
const key = field(next);
|
|
181
|
-
const existing = acc.get(key).getOrElseValue(Collection.empty);
|
|
182
|
-
return acc.set(key, new Collection<T>(existing.toArray.concat(next)));
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
minBy(toNumber: (item: T) => number): T {
|
|
187
|
-
if (this.isEmpty) {
|
|
188
|
-
throw new Error('empty.minBy');
|
|
189
|
-
} else {
|
|
190
|
-
let res = this.head;
|
|
191
|
-
let min = toNumber(res);
|
|
192
|
-
this.toArray.forEach(i => {
|
|
193
|
-
const next = toNumber(i);
|
|
194
|
-
if (next < min) {
|
|
195
|
-
res = i;
|
|
196
|
-
min = next;
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
return res;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
minByOption(toNumber: (item: T) => number): Option<T> {
|
|
204
|
-
return this.isEmpty ? none : some(this.minBy(toNumber));
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
maxBy(toNumber: (item: T) => number): T {
|
|
208
|
-
|
|
209
|
-
if (this.isEmpty) {
|
|
210
|
-
throw new Error('empty.maxBy');
|
|
211
|
-
} else {
|
|
212
|
-
let res = this.head;
|
|
213
|
-
let max = toNumber(res);
|
|
214
|
-
this.toArray.forEach(i => {
|
|
215
|
-
const next = toNumber(i);
|
|
216
|
-
if (next > max) {
|
|
217
|
-
res = i;
|
|
218
|
-
max = next;
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
return res;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
maxByOption(toNumber: (item: T) => number): Option<T> {
|
|
226
|
-
return this.isEmpty ? none : some(this.maxBy(toNumber));
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
partition(p: (item: T) => boolean): [C, C] {
|
|
230
|
-
const array = this.toArray;
|
|
231
|
-
const first = array.filter(i => p(i));
|
|
232
|
-
const second = array.filter(i => !p(i));
|
|
233
|
-
return [this.fromArray(first), this.fromArray(second)];
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
take(n: number): C {
|
|
237
|
-
const items = this.toArray;
|
|
238
|
-
return items.length > n ? this.fromArray(items.slice(0, n)) : this as unknown as C;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
takeRight(n: number): C {
|
|
242
|
-
const array = this.toArray;
|
|
243
|
-
return array.length > n ? this.fromArray(array.slice(array.length - n, array.length)) : this as unknown as C;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
takeWhile(p: (item: T) => boolean): C {
|
|
247
|
-
const array = this.toArray;
|
|
248
|
-
let res = true;
|
|
249
|
-
let i = 0;
|
|
250
|
-
for (; res && i < array.length; i++) {
|
|
251
|
-
res = p(array[i]);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (res) {
|
|
255
|
-
return this as unknown as C;
|
|
256
|
-
} else {
|
|
257
|
-
return this.take(i - 1);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
drop(n: number): C {
|
|
262
|
-
const array = this.toArray;
|
|
263
|
-
if (n >= array.length) {
|
|
264
|
-
return this.fromArray([]);
|
|
265
|
-
} else if (n === 0) {
|
|
266
|
-
return this as unknown as C;
|
|
267
|
-
} else {
|
|
268
|
-
return this.fromArray(array.slice(n, array.length));
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
dropRight(n: number): C {
|
|
273
|
-
const array = this.toArray;
|
|
274
|
-
if (n >= array.length) {
|
|
275
|
-
return this.fromArray([]);
|
|
276
|
-
} else if (n === 0) {
|
|
277
|
-
return this as unknown as C;
|
|
278
|
-
} else {
|
|
279
|
-
return this.fromArray(array.slice(0, array.length - n));
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
dropWhile(p: (item: T) => boolean): C {
|
|
286
|
-
const array = this.toArray;
|
|
287
|
-
let res = true;
|
|
288
|
-
let i = 0;
|
|
289
|
-
for (; res && i < array.length; i++) {
|
|
290
|
-
res = p(array[i]);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
if (res) {
|
|
294
|
-
return this.fromArray([]);
|
|
295
|
-
} else {
|
|
296
|
-
return this.drop(i - 1);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
sliding(length: number, step = 1): Collection<C> {
|
|
302
|
-
if (this.isEmpty) {
|
|
303
|
-
return Collection.empty;
|
|
304
|
-
} else {
|
|
305
|
-
const itemsSize = this.size;
|
|
306
|
-
if (itemsSize <= length) {
|
|
307
|
-
return Collection.of(this as unknown as C);
|
|
308
|
-
} else {
|
|
309
|
-
const result: Array<C> = [];
|
|
310
|
-
let left = 0;
|
|
311
|
-
let done = false;
|
|
312
|
-
let right = length;
|
|
313
|
-
const items = this.toArray;
|
|
314
|
-
while (!done) {
|
|
315
|
-
done = right >= itemsSize;
|
|
316
|
-
result.push(this.fromArray(items.slice(left, right)));
|
|
317
|
-
left += step;
|
|
318
|
-
right = left + length;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
return new Collection(result);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
grouped(length: number): Collection<C> {
|
|
328
|
-
return this.sliding(length, length);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
mkString(separator = ''): string {
|
|
332
|
-
return this.toArray.join(separator);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
/**
|
|
337
|
-
* Sums up the elements of this collection.
|
|
338
|
-
*
|
|
339
|
-
* @param elementToNum a parameter converting an element to a number.
|
|
340
|
-
* @return the sum of all elements produced by elementToNum over the elements of this collection.
|
|
341
|
-
*/
|
|
342
|
-
sum(elementToNum: (element: T) => number): number {
|
|
343
|
-
if (this.isEmpty) {
|
|
344
|
-
return 0;
|
|
345
|
-
} else {
|
|
346
|
-
return this.toArray.reduce<number>((acc, next) => acc + elementToNum(next), 0);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
filter(p: (item: T) => boolean): C {
|
|
351
|
-
return this.fromArray(this.toArray.filter(i => p(i)));
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
filterNot(p: (item: T) => boolean): C {
|
|
355
|
-
return this.fromArray(this.toArray.filter(i => !p(i)));
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
splitAt(n: number): [C, C] {
|
|
359
|
-
return [this.take(n), this.drop(n)];
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
/** Splits this $coll into a prefix/suffix pair according to a predicate.
|
|
363
|
-
*
|
|
364
|
-
* Note: `c span p` is equivalent to (but possibly more efficient than)
|
|
365
|
-
* `(c takeWhile p, c dropWhile p)`, provided the evaluation of the
|
|
366
|
-
* predicate `p` does not cause any side-effects.
|
|
367
|
-
* $orderDependent
|
|
368
|
-
*
|
|
369
|
-
* @param p the test predicate
|
|
370
|
-
* @return a pair consisting of the longest prefix of this $coll whose
|
|
371
|
-
* elements all satisfy `p`, and the rest of this $coll.
|
|
372
|
-
*/
|
|
373
|
-
span(p: (item: T) => boolean): [C, C] {
|
|
374
|
-
return [this.takeWhile(p), this.dropWhile(p)];
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
/** The initial part of the collection without its last element.
|
|
379
|
-
* $willForceEvaluation
|
|
380
|
-
*/
|
|
381
|
-
get init(): C {
|
|
382
|
-
if (this.isEmpty) throw new Error('empty.init');
|
|
383
|
-
return this.dropRight(1);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
/** The rest of the collection without its first element. */
|
|
388
|
-
get tail(): C {
|
|
389
|
-
if (this.isEmpty) throw new Error('empty.tail');
|
|
390
|
-
return this.drop(1);
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
/**
|
|
395
|
-
* Partitions this $coll into a map of ${coll}s according to a discriminator function `key`.
|
|
396
|
-
* Each element in a group is transformed into a value of type `B` using the `value` function.
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
* ```
|
|
400
|
-
* class User {
|
|
401
|
-
* constructor(readonly name: string, readonly age: number)
|
|
402
|
-
* }
|
|
403
|
-
*
|
|
404
|
-
* function namesByAge(users: Collection<User>): Map<number, Collection<string>> {
|
|
405
|
-
* users.groupMap(_ => _.age)(_ => _.name)
|
|
406
|
-
* }
|
|
407
|
-
* ```
|
|
408
|
-
*
|
|
409
|
-
*
|
|
410
|
-
* @param key the discriminator function.
|
|
411
|
-
* @param value the element transformation function
|
|
412
|
-
* @tparam K the type of keys returned by the discriminator function
|
|
413
|
-
* @tparam B the type of values returned by the transformation function
|
|
414
|
-
*/
|
|
415
|
-
groupMap<K, B>(key: (item: T) => K): (value: (_: T) => B) => HashMap<K, Collection<B>> {
|
|
416
|
-
return (value: (i: T) => B) => {
|
|
417
|
-
return this.foldLeft<HashMap<K, Collection<B>>>(HashMap.empty)((acc, next) => {
|
|
418
|
-
const nextKey = key(next);
|
|
419
|
-
const existingColl = acc.getOrElse(nextKey, () => Collection.empty);
|
|
420
|
-
const updatedColl = existingColl.appended(value(next));
|
|
421
|
-
return acc.updated(nextKey, updatedColl);
|
|
422
|
-
});
|
|
423
|
-
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
/**
|
|
429
|
-
* Partitions this $coll into a map according to a discriminator function `key`. All the values that
|
|
430
|
-
* have the same discriminator are then transformed by the `f` function and then reduced into a
|
|
431
|
-
* single value with the `reduce` function.
|
|
432
|
-
*
|
|
433
|
-
* It is equivalent to `groupBy(key).mapValues(_.map(f).reduce(reduce))`, but more efficient.
|
|
434
|
-
*
|
|
435
|
-
* ```
|
|
436
|
-
* occurrences[A](as: Collection<A>): Map<A, number> =
|
|
437
|
-
* as.groupMapReduce<number, number>(identity)(_ => 1)((a, b) => a + b)
|
|
438
|
-
* ```
|
|
439
|
-
*
|
|
440
|
-
* $willForceEvaluation
|
|
441
|
-
*/
|
|
442
|
-
groupMapReduce<K, B>(key: (_: T) => K): GroupMapReduce2<T, K, B> {
|
|
443
|
-
return (value: (i: T) => B) => {
|
|
444
|
-
return (reduce: (v1: B, v2: B) => B) => {
|
|
445
|
-
return this.foldLeft<HashMap<K, B>>(HashMap.empty)((acc, next) => {
|
|
446
|
-
const nextKey = key(next);
|
|
447
|
-
const nextValue = value(next);
|
|
448
|
-
return acc.updated(nextKey, acc.get(nextKey).map(e => reduce(e, nextValue)).getOrElseValue(nextValue));
|
|
449
|
-
});
|
|
450
|
-
};
|
|
451
|
-
};
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
/** Computes a prefix scan of the elements of the collection.
|
|
456
|
-
*
|
|
457
|
-
* Note: The neutral element `z` may be applied more than once.
|
|
458
|
-
*
|
|
459
|
-
* @tparam B element type of the resulting collection
|
|
460
|
-
* @param z neutral element for the operator `op`
|
|
461
|
-
* @param op the associative operator for the scan
|
|
462
|
-
*
|
|
463
|
-
* @return a new $coll containing the prefix scan of the elements in this $coll
|
|
464
|
-
*/
|
|
465
|
-
scan(z: T): (op: (acc: T, next: T) => T) => C {
|
|
466
|
-
return this.scanLeft(z);
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
scanLeft(z: T): (op: (acc: T, next: T) => T) => C {
|
|
470
|
-
return (op: (acc: T, next: T) => T) => {
|
|
471
|
-
const res: T[] = [z];
|
|
472
|
-
let acc: T = z;
|
|
473
|
-
this.toArray.forEach(i => {
|
|
474
|
-
acc = op(acc, i);
|
|
475
|
-
res.push(acc);
|
|
476
|
-
});
|
|
477
|
-
return this.fromArray(res);
|
|
478
|
-
};
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
/** Produces a collection containing cumulative results of applying the operator going right to left.
|
|
482
|
-
* The head of the collection is the last cumulative result.
|
|
483
|
-
* $willNotTerminateInf
|
|
484
|
-
* $orderDependent
|
|
485
|
-
* $willForceEvaluation
|
|
486
|
-
*
|
|
487
|
-
* Example:
|
|
488
|
-
* ```
|
|
489
|
-
* Collection.of(1, 2, 3, 4).scanRight(0)((a, b) => a + b) == Collection.of(10, 9, 7, 4, 0)
|
|
490
|
-
* ```
|
|
491
|
-
*
|
|
492
|
-
* @tparam B the type of the elements in the resulting collection
|
|
493
|
-
* @param z the initial value
|
|
494
|
-
* @param op the binary operator applied to the intermediate result and the element
|
|
495
|
-
* @return collection with intermediate results
|
|
496
|
-
*/
|
|
497
|
-
scanRight(z: T): (op: (acc: T, next: T) => T) => C {
|
|
498
|
-
return (op: (acc: T, next: T) => T) => {
|
|
499
|
-
const res: T[] = [z];
|
|
500
|
-
let acc: T = z;
|
|
501
|
-
this.toArray.reverse().forEach(i => {
|
|
502
|
-
acc = op(acc, i);
|
|
503
|
-
res.push(acc);
|
|
504
|
-
});
|
|
505
|
-
return this.fromArray(res.reverse());
|
|
506
|
-
};
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
get zipWithIndex(): Collection<[T, number]> {
|
|
510
|
-
const res: [T, number][] = [];
|
|
511
|
-
const array = this.toArray;
|
|
512
|
-
for (let i = 0; i < array.length; i++) {
|
|
513
|
-
res.push([array[i], i]);
|
|
514
|
-
}
|
|
515
|
-
return new Collection<[T, number]>(res);
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
/** Iterates over the tails of this $coll. The first value will be this
|
|
519
|
-
* $coll and the final one will be an empty $coll, with the intervening
|
|
520
|
-
* values the results of successive applications of `tail`.
|
|
521
|
-
*
|
|
522
|
-
* @return an iterator over all the tails of this $coll
|
|
523
|
-
* @example `Collection.of(1,2,3).tails = Collection.of(Collection.of(1,2,3), Collection.of(2,3), Collection.of(3), Nil)`
|
|
524
|
-
*/
|
|
525
|
-
get tails(): Collection<C> {
|
|
526
|
-
const array = this.toArray;
|
|
527
|
-
const res: C[] = [];
|
|
528
|
-
for (let i = 0; i <= array.length; i++) {
|
|
529
|
-
res.push(this.takeRight(array.length - i));
|
|
530
|
-
}
|
|
531
|
-
return new Collection<C>(res);
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
/** Iterates over the inits of this $coll. The first value will be this
|
|
535
|
-
* $coll and the final one will be an empty $coll, with the intervening
|
|
536
|
-
* values the results of successive applications of `init`.
|
|
537
|
-
*
|
|
538
|
-
* $willForceEvaluation
|
|
539
|
-
*
|
|
540
|
-
* @return an iterator over all the inits of this $coll
|
|
541
|
-
* @example `Collection.of(1,2,3).inits = Collection.of(Collection.of(1,2,3), Collection.of(1,2), Collection.of(1), Nil)`
|
|
542
|
-
*/
|
|
543
|
-
get inits(): Collection<C> {
|
|
544
|
-
const array = this.toArray;
|
|
545
|
-
const res: C[] = [];
|
|
546
|
-
for (let i = 0; i <= array.length; i++) {
|
|
547
|
-
res.push(this.take(array.length - i));
|
|
548
|
-
}
|
|
549
|
-
return new Collection<C>(res);
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
export type GroupMapReduce3<K, B> = (reduce: (v1: B, v2: B) => B) => HashMap<K, B>;
|
|
556
|
-
export type GroupMapReduce2<T, K, B> = (f: (_: T) => B) => GroupMapReduce3<K, B>;
|
|
557
|
-
|