extra-iterator 0.2.1 → 0.3.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/README.md +1 -1
- package/dist/index.d.ts +19 -18
- package/dist/index.js +57 -32
- package/dist/index.test.d.ts +1 -0
- package/dist/index.test.js +121 -0
- package/package.json +8 -3
package/README.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -2,13 +2,20 @@ interface ArrayIsh<T> {
|
|
|
2
2
|
[index: number]: T;
|
|
3
3
|
length: number;
|
|
4
4
|
}
|
|
5
|
+
export type ExtraIteratorSource<T> = Iterator<T, any, any> | Iterable<T, any, any> | ArrayIsh<T>;
|
|
5
6
|
export declare class ExtraIterator<T> extends Iterator<T, any, any> {
|
|
6
|
-
static from<T>(source:
|
|
7
|
-
static
|
|
8
|
-
static
|
|
9
|
-
static
|
|
7
|
+
static from<T>(source: ExtraIteratorSource<T>): ExtraIterator<T>;
|
|
8
|
+
static zip<A, B>(a: ExtraIteratorSource<A>, b: ExtraIteratorSource<B>): ExtraIterator<[A, B]>;
|
|
9
|
+
static zip<A, B, C>(a: ExtraIteratorSource<A>, b: ExtraIteratorSource<B>, c: ExtraIteratorSource<C>): ExtraIterator<[A, B, C]>;
|
|
10
|
+
static zip<A, B, C, D>(a: ExtraIteratorSource<A>, b: ExtraIteratorSource<B>, c: ExtraIteratorSource<C>, d: ExtraIteratorSource<D>): ExtraIterator<[A, B, C, D]>;
|
|
11
|
+
static zip<A, B, C, D, E>(a: ExtraIteratorSource<A>, b: ExtraIteratorSource<B>, c: ExtraIteratorSource<C>, d: ExtraIteratorSource<D>, e: ExtraIteratorSource<E>): ExtraIterator<[A, B, C, D, E]>;
|
|
12
|
+
static zip<A, B, C, D, E, F>(a: ExtraIteratorSource<A>, b: ExtraIteratorSource<B>, c: ExtraIteratorSource<C>, d: ExtraIteratorSource<D>, e: ExtraIteratorSource<E>, f: ExtraIteratorSource<F>): ExtraIterator<[A, B, C, D, E, F]>;
|
|
13
|
+
static zip<A, B, C, D, E, F, G>(a: ExtraIteratorSource<A>, b: ExtraIteratorSource<B>, c: ExtraIteratorSource<C>, d: ExtraIteratorSource<D>, e: ExtraIteratorSource<E>, f: ExtraIteratorSource<F>, g: ExtraIteratorSource<G>): ExtraIterator<[A, B, C, D, E, F, G]>;
|
|
14
|
+
static zip<A, B, C, D, E, F, G, H>(a: ExtraIteratorSource<A>, b: ExtraIteratorSource<B>, c: ExtraIteratorSource<C>, d: ExtraIteratorSource<D>, e: ExtraIteratorSource<E>, f: ExtraIteratorSource<F>, g: ExtraIteratorSource<G>, h: ExtraIteratorSource<H>): ExtraIterator<[A, B, C, D, E, F, G, H]>;
|
|
15
|
+
static zip<T>(...iterables: ExtraIteratorSource<T>[]): ExtraIterator<T[]>;
|
|
10
16
|
static empty<T = any>(): ExtraIterator<T>;
|
|
11
|
-
static count(
|
|
17
|
+
static count(): ExtraIterator<number>;
|
|
18
|
+
static count(end: number): ExtraIterator<number>;
|
|
12
19
|
static count(start: number, end: number): ExtraIterator<number>;
|
|
13
20
|
static count(start: number, end: number, interval: number): ExtraIterator<number>;
|
|
14
21
|
static repeat<T>(count: number, value: T): ExtraIterator<T>;
|
|
@@ -30,26 +37,20 @@ export declare class ExtraIterator<T> extends Iterator<T, any, any> {
|
|
|
30
37
|
first(): T | undefined;
|
|
31
38
|
last(): T | undefined;
|
|
32
39
|
at(index: number): T | undefined;
|
|
33
|
-
|
|
34
|
-
|
|
40
|
+
concat(items: Iterable<T>): ExtraIterator<T>;
|
|
41
|
+
append(item: T): ExtraIterator<T>;
|
|
35
42
|
prependMany(items: Iterable<T>): ExtraIterator<T>;
|
|
36
|
-
|
|
43
|
+
prepend(item: T): ExtraIterator<T>;
|
|
37
44
|
takeWhile(predicate: (value: T, index: number) => boolean): ExtraIterator<T>;
|
|
38
45
|
dropWhile(predicate: (value: T, index: number) => boolean): ExtraIterator<T>;
|
|
39
46
|
chunk(size: number): ExtraIterator<T[]>;
|
|
40
|
-
/**
|
|
41
|
-
* Pairs with another iterable to form an iterator of pairs.
|
|
42
|
-
* // TODO Expand to support more than 2 iterables
|
|
43
|
-
*/
|
|
44
47
|
zip<U>(other: Iterable<U>): ExtraIterator<[T, U]>;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
* // TODO Expand to support more than 2 iterables
|
|
48
|
-
*/
|
|
49
|
-
unzip(): T extends [infer U, infer V] ? [ExtraIterator<U>, ExtraIterator<V>] : never;
|
|
48
|
+
interpose<U>(separator: U): ExtraIterator<T | U>;
|
|
49
|
+
interleave<U>(other: ExtraIteratorSource<U>): ExtraIterator<T | U>;
|
|
50
50
|
splice(startIndex: number, deleteCount: number, ...newItems: T[]): ExtraIterator<T>;
|
|
51
|
-
|
|
51
|
+
defaultIfEmpty(provider: () => T): ExtraIterator<T>;
|
|
52
52
|
collect<U>(collectfn: ((iter: Iterable<T>) => U)): U;
|
|
53
53
|
toSortedBy(...keys: (keyof T)[]): T[];
|
|
54
|
+
count(): number;
|
|
54
55
|
}
|
|
55
56
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -10,24 +10,21 @@ export class ExtraIterator extends Iterator {
|
|
|
10
10
|
}
|
|
11
11
|
return new ExtraIterator(source);
|
|
12
12
|
}
|
|
13
|
-
static
|
|
14
|
-
return new ExtraIterator(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return new ExtraIterator(Object.entries(subject));
|
|
13
|
+
static zip(...iterables) {
|
|
14
|
+
return new ExtraIterator(function* () {
|
|
15
|
+
for (let iterators = iterables.map(iterable => ExtraIterator.from(iterable)), results; results = iterators.map(iterator => iterator.next()),
|
|
16
|
+
results.every(value => !value.done);) {
|
|
17
|
+
yield results.map(value => value.value);
|
|
18
|
+
}
|
|
19
|
+
}().toArray());
|
|
21
20
|
}
|
|
22
21
|
static empty() {
|
|
23
22
|
return new ExtraIterator([]);
|
|
24
23
|
}
|
|
25
|
-
static count(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
interval ??= 1;
|
|
24
|
+
static count(...args) {
|
|
25
|
+
const [start, end, interval] = args.length === 0 ? [0, Infinity, 1]
|
|
26
|
+
: args.length === 1 ? [0, args[0], 1]
|
|
27
|
+
: [args[0], args[1], args[2] ?? 1];
|
|
31
28
|
return new ExtraIterator(function* () {
|
|
32
29
|
for (let counter = start; counter < end; counter += interval) {
|
|
33
30
|
yield counter;
|
|
@@ -140,13 +137,13 @@ export class ExtraIterator extends Iterator {
|
|
|
140
137
|
: index < 0 ? this.take(index).at(0)
|
|
141
138
|
: this.drop(index).first();
|
|
142
139
|
}
|
|
143
|
-
|
|
140
|
+
concat(items) {
|
|
144
141
|
return ExtraIterator.from(function* () {
|
|
145
142
|
yield* this;
|
|
146
143
|
yield* items;
|
|
147
144
|
}.call(this));
|
|
148
145
|
}
|
|
149
|
-
|
|
146
|
+
append(item) {
|
|
150
147
|
return ExtraIterator.from(function* () {
|
|
151
148
|
yield* this;
|
|
152
149
|
yield item;
|
|
@@ -158,7 +155,7 @@ export class ExtraIterator extends Iterator {
|
|
|
158
155
|
yield* this;
|
|
159
156
|
}.call(this));
|
|
160
157
|
}
|
|
161
|
-
|
|
158
|
+
prepend(item) {
|
|
162
159
|
return ExtraIterator.from(function* () {
|
|
163
160
|
yield item;
|
|
164
161
|
yield* this;
|
|
@@ -192,10 +189,6 @@ export class ExtraIterator extends Iterator {
|
|
|
192
189
|
}
|
|
193
190
|
}.call(this));
|
|
194
191
|
}
|
|
195
|
-
/**
|
|
196
|
-
* Pairs with another iterable to form an iterator of pairs.
|
|
197
|
-
* // TODO Expand to support more than 2 iterables
|
|
198
|
-
*/
|
|
199
192
|
zip(other) {
|
|
200
193
|
return ExtraIterator.from(function* () {
|
|
201
194
|
const otherIterator = Iterator.from(other);
|
|
@@ -204,15 +197,31 @@ export class ExtraIterator extends Iterator {
|
|
|
204
197
|
}
|
|
205
198
|
}.call(this));
|
|
206
199
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
200
|
+
interpose(separator) {
|
|
201
|
+
return ExtraIterator.from(function* () {
|
|
202
|
+
for (let next = this.next(); !next.done;) {
|
|
203
|
+
yield next.value;
|
|
204
|
+
next = this.next();
|
|
205
|
+
if (!next.done) {
|
|
206
|
+
yield separator;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}.call(this));
|
|
210
|
+
}
|
|
211
|
+
interleave(other) {
|
|
212
|
+
return ExtraIterator.from(function* () {
|
|
213
|
+
const otherIterator = ExtraIterator.from(other);
|
|
214
|
+
for (let next, otherNext; next = this.next(),
|
|
215
|
+
otherNext = otherIterator.next(),
|
|
216
|
+
!next.done || !otherNext.done;) {
|
|
217
|
+
if (!next.done) {
|
|
218
|
+
yield next.value;
|
|
219
|
+
}
|
|
220
|
+
if (!otherNext.done) {
|
|
221
|
+
yield otherNext.value;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}.call(this));
|
|
216
225
|
}
|
|
217
226
|
splice(startIndex, deleteCount, ...newItems) {
|
|
218
227
|
if (startIndex < 0) {
|
|
@@ -230,8 +239,17 @@ export class ExtraIterator extends Iterator {
|
|
|
230
239
|
}
|
|
231
240
|
}.call(this));
|
|
232
241
|
}
|
|
233
|
-
|
|
234
|
-
return
|
|
242
|
+
defaultIfEmpty(provider) {
|
|
243
|
+
return ExtraIterator.from(function* () {
|
|
244
|
+
const result = this.next();
|
|
245
|
+
if (result.done) {
|
|
246
|
+
yield provider();
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
yield result.value;
|
|
250
|
+
yield* this;
|
|
251
|
+
}
|
|
252
|
+
}.call(this));
|
|
235
253
|
}
|
|
236
254
|
collect(collectfn) {
|
|
237
255
|
return collectfn(this);
|
|
@@ -248,4 +266,11 @@ export class ExtraIterator extends Iterator {
|
|
|
248
266
|
return 0;
|
|
249
267
|
});
|
|
250
268
|
}
|
|
269
|
+
count() {
|
|
270
|
+
let count = 0;
|
|
271
|
+
for (let next; next = this.next(), !next.done;) {
|
|
272
|
+
count++;
|
|
273
|
+
}
|
|
274
|
+
return count;
|
|
275
|
+
}
|
|
251
276
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { ExtraIterator } from './index';
|
|
2
|
+
import { describe, it } from 'node:test';
|
|
3
|
+
import { expect } from 'expect';
|
|
4
|
+
describe('ExtraIterator', () => {
|
|
5
|
+
it('should create an ExtraIterator from an array', () => {
|
|
6
|
+
const array = [1, 2, 3];
|
|
7
|
+
const iterator = ExtraIterator.from(array);
|
|
8
|
+
expect(iterator.toArray()).toEqual(array);
|
|
9
|
+
});
|
|
10
|
+
it('should zip two iterators', () => {
|
|
11
|
+
const a = ExtraIterator.from([1, 2, 3]);
|
|
12
|
+
const b = ExtraIterator.from(['a', 'b', 'c']);
|
|
13
|
+
const zipped = ExtraIterator.zip(a, b);
|
|
14
|
+
expect(zipped.toArray()).toEqual([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
15
|
+
});
|
|
16
|
+
it('should count from 0 to a given number', () => {
|
|
17
|
+
const iterator = ExtraIterator.count(5);
|
|
18
|
+
expect(iterator.toArray()).toEqual([0, 1, 2, 3, 4]);
|
|
19
|
+
});
|
|
20
|
+
it('should repeat a value a given number of times', () => {
|
|
21
|
+
const iterator = ExtraIterator.repeat(3, 'x');
|
|
22
|
+
expect(iterator.toArray()).toEqual(['x', 'x', 'x']);
|
|
23
|
+
});
|
|
24
|
+
it('should filter values based on a predicate', () => {
|
|
25
|
+
const iterator = ExtraIterator.from([1, 2, 3, 4]).filter(x => x % 2 === 0);
|
|
26
|
+
expect(iterator.toArray()).toEqual([2, 4]);
|
|
27
|
+
});
|
|
28
|
+
it('should map values using a callback function', () => {
|
|
29
|
+
const iterator = ExtraIterator.from([1, 2, 3]).map(x => x * 2);
|
|
30
|
+
expect(iterator.toArray()).toEqual([2, 4, 6]);
|
|
31
|
+
});
|
|
32
|
+
it('should take a limited number of values', () => {
|
|
33
|
+
const iterator = ExtraIterator.from([1, 2, 3, 4]).take(2);
|
|
34
|
+
expect(iterator.toArray()).toEqual([1, 2]);
|
|
35
|
+
});
|
|
36
|
+
it('should drop a given number of values', () => {
|
|
37
|
+
const iterator = ExtraIterator.from([1, 2, 3, 4]).drop(2);
|
|
38
|
+
expect(iterator.toArray()).toEqual([3, 4]);
|
|
39
|
+
});
|
|
40
|
+
it('should flatten nested iterables', () => {
|
|
41
|
+
const iterator = ExtraIterator.from([[1, 2], [3, 4]]).flatten();
|
|
42
|
+
expect(iterator.toArray()).toEqual([1, 2, 3, 4]);
|
|
43
|
+
});
|
|
44
|
+
it('should return the first value', () => {
|
|
45
|
+
const iterator = ExtraIterator.from([1, 2, 3]);
|
|
46
|
+
expect(iterator.first()).toBe(1);
|
|
47
|
+
});
|
|
48
|
+
it('should return the last value', () => {
|
|
49
|
+
const iterator = ExtraIterator.from([1, 2, 3]);
|
|
50
|
+
expect(iterator.last()).toBe(3);
|
|
51
|
+
});
|
|
52
|
+
it('should return a value at a specific index', () => {
|
|
53
|
+
const iterator = ExtraIterator.from([1, 2, 3]);
|
|
54
|
+
expect(iterator.at(1)).toBe(2);
|
|
55
|
+
});
|
|
56
|
+
it('should interpose a separator between values', () => {
|
|
57
|
+
const iterator = ExtraIterator.from([1, 2, 3]).interpose(0);
|
|
58
|
+
expect(iterator.toArray()).toEqual([1, 0, 2, 0, 3]);
|
|
59
|
+
});
|
|
60
|
+
it('should chunk values into groups of a given size', () => {
|
|
61
|
+
const iterator = ExtraIterator.from([1, 2, 3, 4]).chunk(2);
|
|
62
|
+
expect(iterator.toArray()).toEqual([[1, 2], [3, 4]]);
|
|
63
|
+
});
|
|
64
|
+
it('should remove duplicate values', () => {
|
|
65
|
+
const iterator = ExtraIterator.from([1, 2, 2, 3]).uniq();
|
|
66
|
+
expect(iterator.toArray()).toEqual([1, 2, 3]);
|
|
67
|
+
});
|
|
68
|
+
it('should compact values by removing null and undefined', () => {
|
|
69
|
+
const iterator = ExtraIterator.from([1, null, 2, undefined, 3]).compact();
|
|
70
|
+
expect(iterator.toArray()).toEqual([1, 2, 3]);
|
|
71
|
+
});
|
|
72
|
+
it('should concatenate two iterators', () => {
|
|
73
|
+
const a = ExtraIterator.from([1, 2]);
|
|
74
|
+
const b = ExtraIterator.from([3, 4]);
|
|
75
|
+
const concatenated = a.concat(b);
|
|
76
|
+
expect(concatenated.toArray()).toEqual([1, 2, 3, 4]);
|
|
77
|
+
});
|
|
78
|
+
it('should prepend a value to the iterator', () => {
|
|
79
|
+
const iterator = ExtraIterator.from([2, 3]).prepend(1);
|
|
80
|
+
expect(iterator.toArray()).toEqual([1, 2, 3]);
|
|
81
|
+
});
|
|
82
|
+
it('should append a value to the iterator', () => {
|
|
83
|
+
const iterator = ExtraIterator.from([1, 2]).append(3);
|
|
84
|
+
expect(iterator.toArray()).toEqual([1, 2, 3]);
|
|
85
|
+
});
|
|
86
|
+
it('should take values while a predicate is true', () => {
|
|
87
|
+
const iterator = ExtraIterator.from([1, 2, 3, 4]).takeWhile(x => x < 3);
|
|
88
|
+
expect(iterator.toArray()).toEqual([1, 2]);
|
|
89
|
+
});
|
|
90
|
+
it('should drop values while a predicate is true', () => {
|
|
91
|
+
const iterator = ExtraIterator.from([1, 2, 3, 4]).dropWhile(x => x < 3);
|
|
92
|
+
expect(iterator.toArray()).toEqual([3, 4]);
|
|
93
|
+
});
|
|
94
|
+
it('should interleave two iterators', () => {
|
|
95
|
+
const a = ExtraIterator.from([1, 3]);
|
|
96
|
+
const b = ExtraIterator.from([2, 4]);
|
|
97
|
+
const interleaved = a.interleave(b);
|
|
98
|
+
expect(interleaved.toArray()).toEqual([1, 2, 3, 4]);
|
|
99
|
+
});
|
|
100
|
+
it('should splice values in the iterator', () => {
|
|
101
|
+
const iterator = ExtraIterator.from([1, 2, 3, 4]).splice(1, 2, 5, 6);
|
|
102
|
+
expect(iterator.toArray()).toEqual([1, 5, 6, 4]);
|
|
103
|
+
});
|
|
104
|
+
it('should provide a default value if the iterator is empty', () => {
|
|
105
|
+
const iterator = ExtraIterator.empty().defaultIfEmpty(() => 42);
|
|
106
|
+
expect(iterator.toArray()).toEqual([42]);
|
|
107
|
+
});
|
|
108
|
+
it('should group values by a key', () => {
|
|
109
|
+
const iterator = ExtraIterator.from(['apple', 'banana', 'apricot']);
|
|
110
|
+
const grouped = iterator.groupBy(word => word[0]);
|
|
111
|
+
expect(grouped).toEqual({
|
|
112
|
+
a: ['apple', 'apricot'],
|
|
113
|
+
b: ['banana'],
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
it('should collect values using a custom collector', () => {
|
|
117
|
+
const iterator = ExtraIterator.from([1, 2, 3]);
|
|
118
|
+
const sum = iterator.collect(iter => Array.from(iter).reduce((a, b) => a + b, 0));
|
|
119
|
+
expect(sum).toBe(6);
|
|
120
|
+
});
|
|
121
|
+
});
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "An extension of the Iterator class with additional utility helper functions.",
|
|
4
4
|
"author": "Leonardo Raele <leonardoraele@gmail.com>",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.3.1",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": "./dist/index.js",
|
|
@@ -13,13 +13,18 @@
|
|
|
13
13
|
"dist"
|
|
14
14
|
],
|
|
15
15
|
"scripts": {
|
|
16
|
-
"test": "
|
|
16
|
+
"test": "run-s test:types test:unit",
|
|
17
|
+
"test:types": "tsc --noEmit",
|
|
18
|
+
"test:unit": "node --import=tsx --test **/*.test.ts",
|
|
17
19
|
"build": "tsc",
|
|
18
20
|
"prebuild": "rimraf dist",
|
|
19
|
-
"prepack": "
|
|
21
|
+
"prepack": "run-s test build"
|
|
20
22
|
},
|
|
21
23
|
"devDependencies": {
|
|
24
|
+
"expect": "^29.7.0",
|
|
25
|
+
"npm-run-all": "^4.1.5",
|
|
22
26
|
"rimraf": "^6.0.1",
|
|
27
|
+
"tsx": "^4.19.3",
|
|
23
28
|
"typescript": "^5.8.3"
|
|
24
29
|
},
|
|
25
30
|
"keywords": [
|