extra-iterator 0.11.0 → 0.11.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/index.d.ts CHANGED
@@ -163,11 +163,11 @@ export declare class ExtraIterator<T> extends Iterator<T, any, any> {
163
163
  * @example
164
164
  *
165
165
  * ExtraIterator.from([4, 5, 6])
166
- * .prependMany([1, 2, 3])
166
+ * .prependAll([1, 2, 3])
167
167
  * .toArray()
168
168
  * // returns [1, 2, 3, 4, 5, 6]
169
169
  */
170
- prependMany<U>(items: Iterable<U>): ExtraIterator<T | U>;
170
+ prependAll<U>(items: Iterable<U>): ExtraIterator<T | U>;
171
171
  /**
172
172
  * Creates a new iterator that invokes the provided callback function over each element of this iterator and yields
173
173
  * the elements for which the callback returns `true`, only for as long as the callback returns `true`.
@@ -213,9 +213,9 @@ export declare class ExtraIterator<T> extends Iterator<T, any, any> {
213
213
  /**
214
214
  * Groups the elements in this iterator into groups of variable size.
215
215
  *
216
- * This method calls the provided predicate function for each pair of adjacent elements in this iterator. It should
217
- * return `true` if the elements should belong to the same group, or `false` if they should belong to different
218
- * groups.
216
+ * This method calls the provided predicate function for each pair of adjacent elements in this iterator. The
217
+ * function should return `true` if the elements should belong to the same group, or `false` if they should belong
218
+ * to different groups.
219
219
  *
220
220
  * The resulting iterator yields arrays of elements that belong to the same group.
221
221
  *
@@ -292,7 +292,8 @@ export declare class ExtraIterator<T> extends Iterator<T, any, any> {
292
292
  */
293
293
  splice(startIndex: number, deleteCount: number, ...newItems: T[]): ExtraIterator<T>;
294
294
  /**
295
- * Returns an iterator the provided element if this iterator is empty; otherwise, it returns this iterator.
295
+ * If this iterator is empty, returns an iterator with the provided element as its only element; otherwise, it
296
+ * returns a copy of this iterator.
296
297
  */
297
298
  defaultIfEmpty(provider: () => T): ExtraIterator<T>;
298
299
  /**
@@ -380,8 +381,8 @@ export declare class ExtraIterator<T> extends Iterator<T, any, any> {
380
381
  *
381
382
  * @example
382
383
  *
383
- * ExtraIterator.from([1, 2, 3]).uniqueness() // returns true
384
- * ExtraIterator.from([1, 2, 3, 1]).uniqueness() // returns false
384
+ * ExtraIterator.from([1, 2, 3]).testUnique() // returns true
385
+ * ExtraIterator.from([1, 2, 3, 1]).testUnique() // returns false
385
386
  */
386
387
  testUnique(mapper?: (value: T) => unknown): boolean;
387
388
  /**
package/dist/index.js CHANGED
@@ -271,11 +271,11 @@ export class ExtraIterator extends Iterator {
271
271
  * @example
272
272
  *
273
273
  * ExtraIterator.from([4, 5, 6])
274
- * .prependMany([1, 2, 3])
274
+ * .prependAll([1, 2, 3])
275
275
  * .toArray()
276
276
  * // returns [1, 2, 3, 4, 5, 6]
277
277
  */
278
- prependMany(items) {
278
+ prependAll(items) {
279
279
  return ExtraIterator.from(function* () {
280
280
  yield* items;
281
281
  yield* this;
@@ -351,9 +351,9 @@ export class ExtraIterator extends Iterator {
351
351
  /**
352
352
  * Groups the elements in this iterator into groups of variable size.
353
353
  *
354
- * This method calls the provided predicate function for each pair of adjacent elements in this iterator. It should
355
- * return `true` if the elements should belong to the same group, or `false` if they should belong to different
356
- * groups.
354
+ * This method calls the provided predicate function for each pair of adjacent elements in this iterator. The
355
+ * function should return `true` if the elements should belong to the same group, or `false` if they should belong
356
+ * to different groups.
357
357
  *
358
358
  * The resulting iterator yields arrays of elements that belong to the same group.
359
359
  *
@@ -373,7 +373,7 @@ export class ExtraIterator extends Iterator {
373
373
  let chunk = [first.value];
374
374
  for (let left = first, right, index = 0; right = this.next(), !right.done; left = right, index++) {
375
375
  if (predicate(left.value, right.value, index, chunk)) {
376
- chunk.push(left.value);
376
+ chunk.push(right.value);
377
377
  }
378
378
  else {
379
379
  yield chunk;
@@ -489,8 +489,7 @@ export class ExtraIterator extends Iterator {
489
489
  */
490
490
  splice(startIndex, deleteCount, ...newItems) {
491
491
  if (startIndex < 0) {
492
- return ExtraIterator.from(this.toArray()
493
- .toSpliced(startIndex, deleteCount, ...newItems));
492
+ return ExtraIterator.from(this.toArray().toSpliced(startIndex, deleteCount, ...newItems));
494
493
  }
495
494
  return ExtraIterator.from(function* () {
496
495
  for (let index = 0, next; next = this.next(), !next.done; index++) {
@@ -504,7 +503,8 @@ export class ExtraIterator extends Iterator {
504
503
  }.call(this));
505
504
  }
506
505
  /**
507
- * Returns an iterator the provided element if this iterator is empty; otherwise, it returns this iterator.
506
+ * If this iterator is empty, returns an iterator with the provided element as its only element; otherwise, it
507
+ * returns a copy of this iterator.
508
508
  */
509
509
  defaultIfEmpty(provider) {
510
510
  return ExtraIterator.from(function* () {
@@ -528,9 +528,6 @@ export class ExtraIterator extends Iterator {
528
528
  loop(times = Infinity) {
529
529
  return ExtraIterator.from(function* () {
530
530
  const values = this.toArray();
531
- if (values.length === 0) {
532
- return;
533
- }
534
531
  for (let i = 0; i < times; i++) {
535
532
  yield* values;
536
533
  }
@@ -663,8 +660,8 @@ export class ExtraIterator extends Iterator {
663
660
  *
664
661
  * @example
665
662
  *
666
- * ExtraIterator.from([1, 2, 3]).uniqueness() // returns true
667
- * ExtraIterator.from([1, 2, 3, 1]).uniqueness() // returns false
663
+ * ExtraIterator.from([1, 2, 3]).testUnique() // returns true
664
+ * ExtraIterator.from([1, 2, 3, 1]).testUnique() // returns false
668
665
  */
669
666
  testUnique(mapper) {
670
667
  const seen = new Set();
@@ -7,12 +7,24 @@ describe(ExtraIterator.name, () => {
7
7
  const iterator = ExtraIterator.from(array);
8
8
  expect(iterator.toArray()).toEqual(array);
9
9
  });
10
+ it('should create an ExtraIterator from an "array-like" object', () => {
11
+ const arrayLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 };
12
+ const iterator = ExtraIterator.from(arrayLike);
13
+ expect(iterator.toArray()).toEqual(['a', 'b', 'c']);
14
+ });
10
15
  it('should zip two iterators', () => {
11
16
  const a = ExtraIterator.from([1, 2, 3]);
12
17
  const b = ExtraIterator.from(['a', 'b', 'c']);
13
- const zipped = ExtraIterator.zip(a, b);
18
+ const zipped = a.zip(b);
14
19
  expect(zipped.toArray()).toEqual([[1, 'a'], [2, 'b'], [3, 'c']]);
15
20
  });
21
+ it('should zip three iterators', () => {
22
+ const a = ExtraIterator.from([1, 2, 3]);
23
+ const b = ExtraIterator.from(['a', 'b', 'c']);
24
+ const c = ExtraIterator.from([true, false, true]);
25
+ const zipped = ExtraIterator.zip(a, b, c);
26
+ expect(zipped.toArray()).toEqual([[1, 'a', true], [2, 'b', false], [3, 'c', true]]);
27
+ });
16
28
  it('should count from 0 to a given number', () => {
17
29
  const iterator = ExtraIterator.count().take(5);
18
30
  expect(iterator.toArray()).toEqual([0, 1, 2, 3, 4]);
@@ -42,6 +54,10 @@ describe(ExtraIterator.name, () => {
42
54
  const iterator = ExtraIterator.from([1, 2, 3, 4]).take(2);
43
55
  expect(iterator.toArray()).toEqual([1, 2]);
44
56
  });
57
+ it('should take the last values of the sequence', () => {
58
+ const iterator = ExtraIterator.from([1, 2, 3, 4]).take(-2);
59
+ expect(iterator.toArray()).toEqual([3, 4]);
60
+ });
45
61
  it('should drop a given number of values', () => {
46
62
  const iterator = ExtraIterator.from([1, 2, 3, 4]).drop(2);
47
63
  expect(iterator.toArray()).toEqual([3, 4]);
@@ -54,9 +70,15 @@ describe(ExtraIterator.name, () => {
54
70
  const iterator = ExtraIterator.from([1, 2, 3]);
55
71
  expect(iterator.first()).toBe(1);
56
72
  });
57
- it('should return the last value', () => {
58
- const iterator = ExtraIterator.from([1, 2, 3]);
59
- expect(iterator.last()).toBe(3);
73
+ describe(ExtraIterator.prototype.last.name, () => {
74
+ it('should return the last value if the iterator is not empty', () => {
75
+ const iterator = ExtraIterator.from([1, 2, 3]);
76
+ expect(iterator.last()).toBe(3);
77
+ });
78
+ it('should return undefined if the iterator is empty', () => {
79
+ const iterator = ExtraIterator.empty();
80
+ expect(iterator.last()).toBeUndefined();
81
+ });
60
82
  });
61
83
  it('should return a value at a specific index', () => {
62
84
  const iterator = ExtraIterator.from([1, 2, 3]);
@@ -92,6 +114,10 @@ describe(ExtraIterator.name, () => {
92
114
  const iterator = ExtraIterator.from([2, 3]).prepend(1);
93
115
  expect(iterator.toArray()).toEqual([1, 2, 3]);
94
116
  });
117
+ it('should prepend multiple values to the iterator', () => {
118
+ const iterator = ExtraIterator.from([4, 5, 6]).prependAll([1, 2, 3]);
119
+ expect(iterator.toArray()).toEqual([1, 2, 3, 4, 5, 6]);
120
+ });
95
121
  it('should append a value to the iterator', () => {
96
122
  const iterator = ExtraIterator.from([1, 2]).append(3);
97
123
  expect(iterator.toArray()).toEqual([1, 2, 3]);
@@ -114,9 +140,19 @@ describe(ExtraIterator.name, () => {
114
140
  const iterator = ExtraIterator.from([1, 2, 3, 4]).splice(1, 2, 5, 6);
115
141
  expect(iterator.toArray()).toEqual([1, 5, 6, 4]);
116
142
  });
117
- it('should provide a default value if the iterator is empty', () => {
118
- const iterator = ExtraIterator.empty().defaultIfEmpty(() => 42);
119
- expect(iterator.toArray()).toEqual([42]);
143
+ it('should splice values from the end of the iterator', () => {
144
+ const iterator = ExtraIterator.from([1, 2, 3, 4]).splice(-3, 2, 5, 6);
145
+ expect(iterator.toArray()).toEqual([1, 5, 6, 4]);
146
+ });
147
+ describe('defaultIfEmpty', () => {
148
+ it('should provide a default value if the iterator is empty', () => {
149
+ const iterator = ExtraIterator.empty().defaultIfEmpty(() => 42);
150
+ expect(iterator.toArray()).toEqual([42]);
151
+ });
152
+ it('should relay the iterator itself if it is not empty', () => {
153
+ const iterator = ExtraIterator.from([1, 2, 3]).defaultIfEmpty(() => 42);
154
+ expect(iterator.toArray()).toEqual([1, 2, 3]);
155
+ });
120
156
  });
121
157
  it('should group values by a key', () => {
122
158
  const iterator = ExtraIterator.from(['apple', 'banana', 'apricot']);
@@ -171,6 +207,16 @@ describe(ExtraIterator.name, () => {
171
207
  .toArray();
172
208
  expect(result).toEqual([[1, 1], [2], [3, 3, 3], [2, 2]]);
173
209
  });
210
+ it('should chunk using a key selector function', () => {
211
+ const result = ExtraIterator.from(['apple', 'apricot', 'banana', 'avocado'])
212
+ .chunkWith((lhs, rhs) => lhs[0] === rhs[0])
213
+ .toArray();
214
+ expect(result).toEqual([['apple', 'apricot'], ['banana'], ['avocado']]);
215
+ });
216
+ it('should build an empty iterator for an empty iterator', () => {
217
+ const result = ExtraIterator.from([]).chunkWith((lhs, rhs) => lhs === rhs).toArray();
218
+ expect(result).toEqual([]);
219
+ });
174
220
  });
175
221
  it('should create a chain of responsibility function', () => {
176
222
  const humanizeDuration = ExtraIterator.from([
@@ -191,9 +237,18 @@ describe(ExtraIterator.name, () => {
191
237
  const chain = handlers.toChainOfResponsibilityFunction(next => next());
192
238
  expect(() => chain()).toThrow();
193
239
  });
194
- it('should repeat values', () => {
195
- const iterator = ExtraIterator.from([1, 2, 3]).loop(3);
196
- expect(iterator.toArray()).toEqual([1, 2, 3, 1, 2, 3, 1, 2, 3]);
240
+ describe(ExtraIterator.prototype.loop.name, () => {
241
+ it('should repeat values', () => {
242
+ const iterator = ExtraIterator.from([1, 2, 3]).loop(3);
243
+ expect(iterator.toArray()).toEqual([1, 2, 3, 1, 2, 3, 1, 2, 3]);
244
+ });
245
+ it('should yield an empty iterator if the count is equal to or lower than 0', () => {
246
+ expect(ExtraIterator.from([1, 2, 3]).loop(0).toArray()).toEqual([]);
247
+ expect(ExtraIterator.from([1, 2, 3]).loop(-1).toArray()).toEqual([]);
248
+ expect(ExtraIterator.from([1, 2, 3]).loop(-3).toArray()).toEqual([]);
249
+ expect(ExtraIterator.from([1, 2, 3]).loop(-4).toArray()).toEqual([]);
250
+ expect(ExtraIterator.from([1, 2, 3]).loop(-99999).toArray()).toEqual([]);
251
+ });
197
252
  });
198
253
  describe(ExtraIterator.range.name, () => {
199
254
  it('should iterate over ranges', () => {
@@ -216,4 +271,42 @@ describe(ExtraIterator.name, () => {
216
271
  expect(() => ExtraIterator.range(0, 10, { step: 0 }).toArray()).toThrow();
217
272
  });
218
273
  });
274
+ it('should count the number of elements in the iterator', () => {
275
+ expect(ExtraIterator.from([1, 2, 3]).count()).toBe(3);
276
+ expect(ExtraIterator.empty().count()).toBe(0);
277
+ });
278
+ describe(ExtraIterator.prototype.testUnique.name, () => {
279
+ it('should return true if all values are unique', () => {
280
+ expect(ExtraIterator.from([1, 2, 3]).testUnique()).toBe(true);
281
+ });
282
+ it('should return false if there are duplicate values', () => {
283
+ expect(ExtraIterator.from([1, 2, 2, 3]).testUnique()).toBe(false);
284
+ });
285
+ it('should return true for an empty iterator', () => {
286
+ expect(ExtraIterator.empty().testUnique()).toBe(true);
287
+ });
288
+ });
289
+ describe(ExtraIterator.prototype.withEach.name, () => {
290
+ it('should perform a side effect for each value', () => {
291
+ const sideEffects = [];
292
+ const iterator = ExtraIterator.from([1, 2, 3]).withEach(x => void sideEffects.push(x));
293
+ expect(iterator.toArray()).toEqual([1, 2, 3]);
294
+ expect(sideEffects).toEqual([1, 2, 3]);
295
+ });
296
+ it('should not perform side effects if the iterator is not consumed', () => {
297
+ const sideEffects = [];
298
+ ExtraIterator.from([1, 2, 3]).withEach(x => void sideEffects.push(x));
299
+ expect(sideEffects).toEqual([]);
300
+ });
301
+ it('should perform side effects even if the iterator is only partially consumed', () => {
302
+ const sideEffects = [];
303
+ const iterator = ExtraIterator.from([1, 2, 3]).withEach(x => void sideEffects.push(x));
304
+ iterator.next();
305
+ expect(sideEffects).toEqual([1]);
306
+ });
307
+ it('should perform side effects on objects', () => {
308
+ const iterator = ExtraIterator.from([{ value: 1 }, { value: 2 }, { value: 3 }]).withEach(obj => obj.value *= 2);
309
+ expect(iterator.toArray()).toEqual([{ value: 2 }, { value: 4 }, { value: 6 }]);
310
+ });
311
+ });
219
312
  });
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.11.0",
6
+ "version": "0.11.1",
7
7
  "type": "module",
8
8
  "exports": {
9
9
  ".": "./dist/index.js",