From d9e82b82bc008351a7249bbe95b9be89289d3c69 Mon Sep 17 00:00:00 2001 From: Voltra Date: Mon, 25 Mar 2024 15:33:09 +0000 Subject: [PATCH 1/5] Add isEmpty and isNotEmpty --- src/Sequence.ts | 85 ++++++++++++++++++++++++++++++-- src/isEmpty.ts | 12 +++++ src/isNotEmpty.ts | 12 +++++ src/operators/sync/isEmpty.ts | 14 ++++++ src/operators/sync/isNotEmpty.ts | 14 ++++++ 5 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 src/isEmpty.ts create mode 100644 src/isNotEmpty.ts create mode 100644 src/operators/sync/isEmpty.ts create mode 100644 src/operators/sync/isNotEmpty.ts diff --git a/src/Sequence.ts b/src/Sequence.ts index faad1ef..c56f004 100644 --- a/src/Sequence.ts +++ b/src/Sequence.ts @@ -1,3 +1,4 @@ +<<<<<<< HEAD import {applyMixins} from "./internal"; import {All as AllOp} from "./operators/sync/all"; import {Any as AnyOp} from "./operators/sync/any"; @@ -32,6 +33,8 @@ import {GroupBy as GroupByOp} from "./operators/sync/groupBy"; import {IndexOf as IndexOfOp} from "./operators/sync/indexOf"; import {IndexOfFirst as IndexOfFirstOp} from "./operators/sync/indexOfFirst"; import {IndexOfLast as IndexOfLastOp} from "./operators/sync/indexOfLast"; +import {IsEmpty as IsEmptyOp} from "./operators/sync/isEmpty"; +import {IsNotEmpty as IsNotEmptyOp} from "./operators/sync/isNotEmpty"; import {JoinToString as JoinToStringOp} from "./operators/sync/joinToString"; import {Last as LastOp} from "./operators/sync/last"; import {LastOrNull as LastOrNullOp} from "./operators/sync/lastOrNull"; @@ -71,6 +74,82 @@ import {ToSet as ToSetOp} from "./operators/sync/toSet"; import {Unzip as UnzipOp} from "./operators/sync/unzip"; import {WithIndex as WithIndexOp} from "./operators/sync/withIndex"; import {Zip as ZipOp} from "./operators/sync/zip"; +======= +import {All} from "./all"; +import {Any} from "./any"; +import {AsIterable} from "./asIterable"; +import {Associate} from "./associate"; +import {AssociateBy} from "./associateBy"; +import {Average} from "./average"; +import {Chunk} from "./chunk"; +import {Contains} from "./contains"; +import {Count} from "./count"; +import {Distinct} from "./distinct"; +import {DistinctBy} from "./distinctBy"; +import {Drop} from "./drop"; +import {DropWhile} from "./dropWhile"; +import {ElementAt} from "./elementAt"; +import {ElementAtOrElse} from "./elementAtOrElse"; +import {ElementAtOrNull} from "./elementAtOrNull"; +import {Filter} from "./filter"; +import {FilterIndexed} from "./filterIndexed"; +import {FilterNot} from "./filterNot"; +import {FilterNotNull} from "./filterNotNull"; +import {First} from "./first"; +import {FirstOrNull} from "./firstOrNull"; +import {FlatMap} from "./flatMap"; +import {Flatten} from "./flatten"; +import {Fold} from "./fold"; +import {FoldIndexed} from "./foldIndexed"; +import {ForEach} from "./forEach"; +import {ForEachIndexed} from "./forEachIndexed"; +import {GroupBy} from "./groupBy"; +import {IndexOf} from "./indexOf"; +import {IndexOfFirst} from "./indexOfFirst"; +import {IndexOfLast} from "./indexOfLast"; +import {IsEmpty} from "./isEmpty"; +import {IsNotEmpty} from "./isNotEmpty"; +import {JoinToString} from "./joinToString"; +import {Last} from "./last"; +import {LastOrNull} from "./lastOrNull"; +import {Map} from "./map"; +import {MapIndexed} from "./mapIndexed"; +import {MapNotNull} from "./mapNotNull"; +import {Max} from "./max"; +import {MaxBy} from "./maxBy"; +import {MaxWith} from "./maxWith"; +import {Merge} from "./merge"; +import {Min} from "./min"; +import {MinBy} from "./minBy"; +import {Minus} from "./minus"; +import {MinWith} from "./minWith"; +import {None} from "./none"; +import {OnEach} from "./onEach"; +import {Partition} from "./partition"; +import {Plus} from "./plus"; +import {Reduce} from "./reduce"; +import {ReduceIndexed} from "./reduceIndexed"; +import {Reverse} from "./reverse"; +import {Single} from "./single"; +import {SingleOrNull} from "./singleOrNull"; +import {Sorted} from "./sorted"; +import {SortedBy} from "./sortedBy"; +import {SortedByDescending} from "./sortedByDescending"; +import {SortedDescending} from "./sortedDescending"; +import {SortedWith} from "./sortedWith"; +import {Sum} from "./sum"; +import {SumBy} from "./sumBy"; +import {Take} from "./take"; +import {TakeWhile} from "./takeWhile"; +import {ToArray} from "./toArray"; +import {ToMap} from "./toMap"; +import {ToSet} from "./toSet"; +import {Unzip} from "./unzip"; +import {WithIndex} from "./withIndex"; +import {Zip} from "./zip"; +import GeneratorIterator from "./GeneratorIterator"; +import GeneratorSeedIterator from "./GeneratorSeedIterator"; +>>>>>>> 09ca0af (Add isEmpty and isNotEmpty) /** * A Sequence provides a fluent functional API consisting @@ -87,7 +166,7 @@ export interface Sequence extends SequenceOperators { */ export interface SequenceOperators extends AllOp, AnyOp, AsIterableOp, AssociateOp, AssociateByOp, AverageOp, ChunkOp, ContainsOp, CountOp, DistinctOp, DistinctByOp, DropOp, DropWhileOp, ElementAtOp, ElementAtOrElseOp, ElementAtOrNullOp, FilterOp, FilterIndexedOp, FilterNotOp, FilterNotNullOp, FirstOp, FirstOrNullOp, FlatMapOp, FlattenOp, FoldOp, - FoldIndexedOp, ForEachOp, ForEachIndexedOp, GroupByOp, IndexOfOp, IndexOfFirstOp, IndexOfLastOp, JoinToStringOp, LastOp, LastOrNullOp, MapOp, MapIndexedOp, MapNotNullOp, MaxOp, MaxByOp, + FoldIndexedOp, ForEachOp, ForEachIndexedOp, GroupByOp, IndexOfOp, IndexOfFirstOp, IndexOfLastOp, IsEmptyOp, IsNotEmptyOp, JoinToStringOp, LastOp, LastOrNullOp, MapOp, MapIndexedOp, MapNotNullOp, MaxOp, MaxByOp, MaxWithOp, MergeOp, MinOp, MinByOp, MinusOp, MinWithOp, NoneOp, OnEachOp, OnEachIndexedOp, PartitionOp, PlusOp, ReduceOp, ReduceIndexedOp, ReverseOp, SingleOp, SingleOrNullOp, SortedOp, SortedByOp, SortedByDescendingOp, SortedDescendingOp, SortedWithOp, SumOp, SumByOp, TakeOp, TakeWhileOp, ToArrayOp, ToAsyncSequenceOp, ToMapOp, ToSetOp, UnzipOp, WithIndexOp, ZipOp { } @@ -99,6 +178,6 @@ export class SequenceImpl { applyMixins(SequenceImpl, [AllOp, AnyOp, AsIterableOp, AssociateOp, AssociateByOp, AverageOp, ChunkOp, ContainsOp, CountOp, DistinctOp, DistinctByOp, DropOp, DropWhileOp, ElementAtOp, ElementAtOrElseOp, ElementAtOrNullOp, FilterOp, FilterIndexedOp, FilterNotOp, FilterNotNullOp, FirstOp, FirstOrNullOp, FlatMapOp, FlattenOp, FoldOp, - FoldIndexedOp, ForEachOp, ForEachIndexedOp, GroupByOp, IndexOfOp, IndexOfFirstOp, IndexOfLastOp, JoinToStringOp, LastOp, LastOrNullOp, MapOp, MapIndexedOp, MapNotNullOp, MaxOp, MaxByOp, + FoldIndexedOp, ForEachOp, ForEachIndexedOp, GroupByOp, IndexOfOp, IndexOfFirstOp, IndexOfLastOp, IsEmptyOp, IsNotEmptyOp, JoinToStringOp, LastOp, LastOrNullOp, MapOp, MapIndexedOp, MapNotNullOp, MaxOp, MaxByOp, MaxWithOp, MergeOp, MinOp, MinByOp, MinusOp, MinWithOp, NoneOp, OnEachOp, OnEachIndexedOp, PartitionOp, PlusOp, ReduceOp, ReduceIndexedOp, ReverseOp, SingleOp, SingleOrNullOp, SortedOp, - SortedByOp, SortedByDescendingOp, SortedDescendingOp, SortedWithOp, SumOp, SumByOp, TakeOp, TakeWhileOp, ToArrayOp, ToAsyncSequenceOp, ToMapOp, ToSetOp, UnzipOp, WithIndexOp, ZipOp]); \ No newline at end of file + SortedByOp, SortedByDescendingOp, SortedDescendingOp, SortedWithOp, SumOp, SumByOp, TakeOp, TakeWhileOp, ToArrayOp, ToAsyncSequenceOp, ToMapOp, ToSetOp, UnzipOp, WithIndexOp, ZipOp]); diff --git a/src/isEmpty.ts b/src/isEmpty.ts new file mode 100644 index 0000000..be1f347 --- /dev/null +++ b/src/isEmpty.ts @@ -0,0 +1,12 @@ +import Sequence from "./Sequence"; + +export class IsEmpty { + /** + * Returns `true` the sequence is empty + * + * @returns {boolean} + */ + isEmpty(this: Sequence) { + return !this.isNotEmpty(); + } +} \ No newline at end of file diff --git a/src/isNotEmpty.ts b/src/isNotEmpty.ts new file mode 100644 index 0000000..7c79d26 --- /dev/null +++ b/src/isNotEmpty.ts @@ -0,0 +1,12 @@ +import Sequence from "./Sequence"; + +export class IsNotEmpty { + /** + * Returns `true` the sequence is not empty + * + * @returns {boolean} + */ + isNotEmpty(this: Sequence) { + return this.any(() => true); + } +} \ No newline at end of file diff --git a/src/operators/sync/isEmpty.ts b/src/operators/sync/isEmpty.ts new file mode 100644 index 0000000..0c09677 --- /dev/null +++ b/src/operators/sync/isEmpty.ts @@ -0,0 +1,14 @@ +import {Sequence} from "../../sequency"; + +export class IsEmpty { + + /** + * Returns `true` the sequence is empty + * + * @returns {boolean} + */ + isEmpty(this: Sequence): boolean { + return !this.isNotEmpty(); + } + +} diff --git a/src/operators/sync/isNotEmpty.ts b/src/operators/sync/isNotEmpty.ts new file mode 100644 index 0000000..e7a1c2a --- /dev/null +++ b/src/operators/sync/isNotEmpty.ts @@ -0,0 +1,14 @@ +import {Sequence} from "../../sequency"; + +export class IsNotEmpty { + + /** + * Returns `true` the sequence is not empty + * + * @returns {boolean} + */ + isNotEmpty(this: Sequence): boolean { + return this.any(() => true); + } + +} From fbf060f60e01268dd755e2623f3795c2348f3239 Mon Sep 17 00:00:00 2001 From: Voltra Date: Mon, 25 Mar 2024 15:39:56 +0000 Subject: [PATCH 2/5] Add tests for isEmpty and isNotEmpty --- test/isEmpty.test.ts | 19 +++++++++++++++++++ test/isNotEmpty.test.ts | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 test/isEmpty.test.ts create mode 100644 test/isNotEmpty.test.ts diff --git a/test/isEmpty.test.ts b/test/isEmpty.test.ts new file mode 100644 index 0000000..79da23b --- /dev/null +++ b/test/isEmpty.test.ts @@ -0,0 +1,19 @@ +import { range, sequenceOf } from "../src/Sequence"; + +describe("isEmpty", () => { + it("returns false for infinite sequences", () => { + expect(range(0, Infinity).isEmpty()).toBeFalsy(); + }); + + it("returns true for empty sequences", () => { + expect(sequenceOf().isEmpty()).toBeTruthy(); + }); + + it("returns true for sequences that would be empty", () => { + expect(sequenceOf(1, 3).filter(x => x % 2 === 0).isEmpty()).toBeTruthy(); + }); + + it("returns false for sequences that would not be empty", () => { + expect(sequenceOf(1, 3).filter(x => x % 2 !== 0).isEmpty()).toBeFalsy(); + }); +}); diff --git a/test/isNotEmpty.test.ts b/test/isNotEmpty.test.ts new file mode 100644 index 0000000..f7abbef --- /dev/null +++ b/test/isNotEmpty.test.ts @@ -0,0 +1,19 @@ +import { range, sequenceOf } from "../src/Sequence"; + +describe("isNotEmpty", () => { + it("returns true for infinite sequences", () => { + expect(range(0, Infinity).isNotEmpty()).toBeTruthy(); + }); + + it("returns false for empty sequences", () => { + expect(sequenceOf().isNotEmpty()).toBeFalsy(); + }); + + it("returns false for sequences that would be empty", () => { + expect(sequenceOf(1, 3).filter(x => x % 2 === 0).isNotEmpty()).toBeFalsy(); + }); + + it("returns true for sequences that would not be empty", () => { + expect(sequenceOf(1, 3).filter(x => x % 2 !== 0).isNotEmpty()).toBeTruthy(); + }); +}); From c333519215ed23e1dcc76002bca69bc0851afb96 Mon Sep 17 00:00:00 2001 From: Ilya Gonchar Date: Fri, 21 Nov 2025 01:23:12 +0100 Subject: [PATCH 3/5] Update README.md --- README.md | 6 ++-- src/Sequence.ts | 77 ----------------------------------------------- src/isEmpty.ts | 12 -------- src/isNotEmpty.ts | 12 -------- 4 files changed, 4 insertions(+), 103 deletions(-) delete mode 100644 src/isEmpty.ts delete mode 100644 src/isNotEmpty.ts diff --git a/README.md b/README.md index 069c892..4071795 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ import { - `generateSequence` returns a sequence generated from the given generator function. - `extendSequence` allows extending sequences with user-defined operations (see [example](https://github.com/Kraken-crypto/sequency/blob/master/test/extendSequence.test.ts)). -Each `Sequence` provides a fluent functional API consisting of intermediate and terminal operations. Intermediate functions (e.g. `filter`, `map`, `sorted`) return a new sequence, thus enabling method chaining. Terminal functions (e.g. `toArray`, `groupBy`, `findLast`) return an arbitrary result. Detailed descriptions of all operations are available in the [API docs](https://github.com/Kraken-crypto/sequency). +Each `Sequence` provides a fluent functional API consisting of intermediate and terminal operations. Intermediate functions (e.g. `filter`, `map`, `sorted`) return a new sequence, thus enabling method chaining. Terminal functions (e.g. `toArray`, `groupBy`, `findLast`) return an arbitrary result. Detailed descriptions of all operations are available in the [API docs](https://kraken-crypto.github.io/sequency). Sequences are **lazily evaluated** to avoid examining all of the input data when it's not necessary. Sequences always perform the minimal amount of operations to gain results. E.g. in a `filter - map - find` sequence both `map` and `find` are executed just one time before returning the single result. @@ -113,7 +113,9 @@ Sequences are **lazily evaluated** to avoid examining all of the input data when ## API documentation -Sequency is fully documented via inline JSDoc comments. When using an IDE like Intellij IDEA or Webstorm the docs are available inline right inside your editor. +Full API documentation is available at [https://kraken-crypto.github.io/sequency](https://kraken-crypto.github.io/sequency). + +Sequency is also fully documented via inline JSDoc comments. When using an IDE like Intellij IDEA or Webstorm the docs are available inline right inside your editor. ## Why Sequency? diff --git a/src/Sequence.ts b/src/Sequence.ts index c56f004..2f33cf8 100644 --- a/src/Sequence.ts +++ b/src/Sequence.ts @@ -1,4 +1,3 @@ -<<<<<<< HEAD import {applyMixins} from "./internal"; import {All as AllOp} from "./operators/sync/all"; import {Any as AnyOp} from "./operators/sync/any"; @@ -74,82 +73,6 @@ import {ToSet as ToSetOp} from "./operators/sync/toSet"; import {Unzip as UnzipOp} from "./operators/sync/unzip"; import {WithIndex as WithIndexOp} from "./operators/sync/withIndex"; import {Zip as ZipOp} from "./operators/sync/zip"; -======= -import {All} from "./all"; -import {Any} from "./any"; -import {AsIterable} from "./asIterable"; -import {Associate} from "./associate"; -import {AssociateBy} from "./associateBy"; -import {Average} from "./average"; -import {Chunk} from "./chunk"; -import {Contains} from "./contains"; -import {Count} from "./count"; -import {Distinct} from "./distinct"; -import {DistinctBy} from "./distinctBy"; -import {Drop} from "./drop"; -import {DropWhile} from "./dropWhile"; -import {ElementAt} from "./elementAt"; -import {ElementAtOrElse} from "./elementAtOrElse"; -import {ElementAtOrNull} from "./elementAtOrNull"; -import {Filter} from "./filter"; -import {FilterIndexed} from "./filterIndexed"; -import {FilterNot} from "./filterNot"; -import {FilterNotNull} from "./filterNotNull"; -import {First} from "./first"; -import {FirstOrNull} from "./firstOrNull"; -import {FlatMap} from "./flatMap"; -import {Flatten} from "./flatten"; -import {Fold} from "./fold"; -import {FoldIndexed} from "./foldIndexed"; -import {ForEach} from "./forEach"; -import {ForEachIndexed} from "./forEachIndexed"; -import {GroupBy} from "./groupBy"; -import {IndexOf} from "./indexOf"; -import {IndexOfFirst} from "./indexOfFirst"; -import {IndexOfLast} from "./indexOfLast"; -import {IsEmpty} from "./isEmpty"; -import {IsNotEmpty} from "./isNotEmpty"; -import {JoinToString} from "./joinToString"; -import {Last} from "./last"; -import {LastOrNull} from "./lastOrNull"; -import {Map} from "./map"; -import {MapIndexed} from "./mapIndexed"; -import {MapNotNull} from "./mapNotNull"; -import {Max} from "./max"; -import {MaxBy} from "./maxBy"; -import {MaxWith} from "./maxWith"; -import {Merge} from "./merge"; -import {Min} from "./min"; -import {MinBy} from "./minBy"; -import {Minus} from "./minus"; -import {MinWith} from "./minWith"; -import {None} from "./none"; -import {OnEach} from "./onEach"; -import {Partition} from "./partition"; -import {Plus} from "./plus"; -import {Reduce} from "./reduce"; -import {ReduceIndexed} from "./reduceIndexed"; -import {Reverse} from "./reverse"; -import {Single} from "./single"; -import {SingleOrNull} from "./singleOrNull"; -import {Sorted} from "./sorted"; -import {SortedBy} from "./sortedBy"; -import {SortedByDescending} from "./sortedByDescending"; -import {SortedDescending} from "./sortedDescending"; -import {SortedWith} from "./sortedWith"; -import {Sum} from "./sum"; -import {SumBy} from "./sumBy"; -import {Take} from "./take"; -import {TakeWhile} from "./takeWhile"; -import {ToArray} from "./toArray"; -import {ToMap} from "./toMap"; -import {ToSet} from "./toSet"; -import {Unzip} from "./unzip"; -import {WithIndex} from "./withIndex"; -import {Zip} from "./zip"; -import GeneratorIterator from "./GeneratorIterator"; -import GeneratorSeedIterator from "./GeneratorSeedIterator"; ->>>>>>> 09ca0af (Add isEmpty and isNotEmpty) /** * A Sequence provides a fluent functional API consisting diff --git a/src/isEmpty.ts b/src/isEmpty.ts deleted file mode 100644 index be1f347..0000000 --- a/src/isEmpty.ts +++ /dev/null @@ -1,12 +0,0 @@ -import Sequence from "./Sequence"; - -export class IsEmpty { - /** - * Returns `true` the sequence is empty - * - * @returns {boolean} - */ - isEmpty(this: Sequence) { - return !this.isNotEmpty(); - } -} \ No newline at end of file diff --git a/src/isNotEmpty.ts b/src/isNotEmpty.ts deleted file mode 100644 index 7c79d26..0000000 --- a/src/isNotEmpty.ts +++ /dev/null @@ -1,12 +0,0 @@ -import Sequence from "./Sequence"; - -export class IsNotEmpty { - /** - * Returns `true` the sequence is not empty - * - * @returns {boolean} - */ - isNotEmpty(this: Sequence) { - return this.any(() => true); - } -} \ No newline at end of file From a52389d3839b1c198cd1dee2c397f309658ff78c Mon Sep 17 00:00:00 2001 From: Ilya Gonchar Date: Fri, 21 Nov 2025 01:28:13 +0100 Subject: [PATCH 4/5] added async versions of isEmpty --- src/AsyncSequence.ts | 6 ++- src/operators/async/isEmpty.ts | 14 +++++++ src/operators/async/isNotEmpty.ts | 14 +++++++ test/operators/async/isEmpty.test.ts | 39 ++++++++++++++++++++ test/operators/async/isNotEmpty.test.ts | 39 ++++++++++++++++++++ test/{ => operators/sync}/isEmpty.test.ts | 3 +- test/{ => operators/sync}/isNotEmpty.test.ts | 3 +- 7 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 src/operators/async/isEmpty.ts create mode 100644 src/operators/async/isNotEmpty.ts create mode 100644 test/operators/async/isEmpty.test.ts create mode 100644 test/operators/async/isNotEmpty.test.ts rename test/{ => operators/sync}/isEmpty.test.ts (90%) rename test/{ => operators/sync}/isNotEmpty.test.ts (91%) diff --git a/src/AsyncSequence.ts b/src/AsyncSequence.ts index 94b5c18..a274cf2 100644 --- a/src/AsyncSequence.ts +++ b/src/AsyncSequence.ts @@ -31,6 +31,8 @@ import {GroupBy as GroupByOp} from "./operators/async/groupBy"; import {IndexOf as IndexOfOp} from "./operators/async/indexOf"; import {IndexOfFirst as IndexOfFirstOp} from "./operators/async/indexOfFirst"; import {IndexOfLast as IndexOfLastOp} from "./operators/async/indexOfLast"; +import {IsEmpty as IsEmptyOp} from "./operators/async/isEmpty"; +import {IsNotEmpty as IsNotEmptyOp} from "./operators/async/isNotEmpty"; import {JoinToString as JoinToStringOp} from "./operators/async/joinToString"; import {Last as LastOp} from "./operators/async/last"; import {LastOrNull as LastOrNullOp} from "./operators/async/lastOrNull"; @@ -87,7 +89,7 @@ export interface AsyncSequence extends AsyncSequenceOperators { */ export interface AsyncSequenceOperators extends AllOp, AnyOp, AsIterableOp, AssociateOp, AssociateByOp, AverageOp, ChunkOp, ContainsOp, CountOp, DistinctOp, DistinctByOp, DropOp, DropWhileOp, ElementAtOp, ElementAtOrElseOp, ElementAtOrNullOp, FilterOp, FilterIndexedOp, FilterNotOp, FilterNotNullOp, FirstOp, FirstOrNullOp, FlatMapOp, FlattenOp, FoldOp, - FoldIndexedOp, ForEachOp, ForEachIndexedOp, GroupByOp, IndexOfOp, IndexOfFirstOp, IndexOfLastOp, JoinToStringOp, LastOp, LastOrNullOp, MapOp, MapIndexedOp, MapNotNullOp, MaxOp, MaxByOp, + FoldIndexedOp, ForEachOp, ForEachIndexedOp, GroupByOp, IndexOfOp, IndexOfFirstOp, IndexOfLastOp, IsEmptyOp, IsNotEmptyOp, JoinToStringOp, LastOp, LastOrNullOp, MapOp, MapIndexedOp, MapNotNullOp, MaxOp, MaxByOp, MaxWithOp, MergeOp, MinOp, MinByOp, MinusOp, MinWithOp, NoneOp, OnEachOp, OnEachIndexedOp, PartitionOp, PlusOp, ReduceOp, ReduceIndexedOp, ReverseOp, SingleOp, SingleOrNullOp, SortedOp, SortedByOp, SortedByDescendingOp, SortedDescendingOp, SortedWithOp, SumOp, SumByOp, TakeOp, TakeWhileOp, ToArrayOp, ToMapOp, ToSetOp, ToSequenceOp, UnzipOp, WithIndexOp, ZipOp { } @@ -99,6 +101,6 @@ export class AsyncSequenceImpl { applyMixins(AsyncSequenceImpl, [AllOp, AnyOp, AsIterableOp, AssociateOp, AssociateByOp, AverageOp, ChunkOp, ContainsOp, CountOp, DistinctOp, DistinctByOp, DropOp, DropWhileOp, ElementAtOp, ElementAtOrElseOp, ElementAtOrNullOp, FilterOp, FilterIndexedOp, FilterNotOp, FilterNotNullOp, FirstOp, FirstOrNullOp, FlatMapOp, FlattenOp, FoldOp, - FoldIndexedOp, ForEachOp, ForEachIndexedOp, GroupByOp, IndexOfOp, IndexOfFirstOp, IndexOfLastOp, JoinToStringOp, LastOp, LastOrNullOp, MapOp, MapIndexedOp, MapNotNullOp, MaxOp, MaxByOp, + FoldIndexedOp, ForEachOp, ForEachIndexedOp, GroupByOp, IndexOfOp, IndexOfFirstOp, IndexOfLastOp, IsEmptyOp, IsNotEmptyOp, JoinToStringOp, LastOp, LastOrNullOp, MapOp, MapIndexedOp, MapNotNullOp, MaxOp, MaxByOp, MaxWithOp, MergeOp, MinOp, MinByOp, MinusOp, MinWithOp, NoneOp, OnEachOp, OnEachIndexedOp, PartitionOp, PlusOp, ReduceOp, ReduceIndexedOp, ReverseOp, SingleOp, SingleOrNullOp, SortedOp, SortedByOp, SortedByDescendingOp, SortedDescendingOp, SortedWithOp, SumOp, SumByOp, TakeOp, TakeWhileOp, ToArrayOp, ToMapOp, ToSetOp, ToSequenceOp, UnzipOp, WithIndexOp, ZipOp]); \ No newline at end of file diff --git a/src/operators/async/isEmpty.ts b/src/operators/async/isEmpty.ts new file mode 100644 index 0000000..0f77ca8 --- /dev/null +++ b/src/operators/async/isEmpty.ts @@ -0,0 +1,14 @@ +import {AsyncSequence} from "../../sequency"; + +export class IsEmpty { + + /** + * Returns `true` the sequence is empty + * + * @returns {Promise} + */ + async isEmpty(this: AsyncSequence): Promise { + return !(await this.isNotEmpty()); + } + +} diff --git a/src/operators/async/isNotEmpty.ts b/src/operators/async/isNotEmpty.ts new file mode 100644 index 0000000..29a2c92 --- /dev/null +++ b/src/operators/async/isNotEmpty.ts @@ -0,0 +1,14 @@ +import {AsyncSequence} from "../../sequency"; + +export class IsNotEmpty { + + /** + * Returns `true` the sequence is not empty + * + * @returns {Promise} + */ + async isNotEmpty(this: AsyncSequence): Promise { + return await this.any(() => true); + } + +} diff --git a/test/operators/async/isEmpty.test.ts b/test/operators/async/isEmpty.test.ts new file mode 100644 index 0000000..e1abcb1 --- /dev/null +++ b/test/operators/async/isEmpty.test.ts @@ -0,0 +1,39 @@ +import {asyncSequenceOf, emptyAsyncSequence, asAsyncSequence} from "../../../src/sequency"; + +describe("isEmpty", () => { + it("returns false for infinite sequences", async () => { + const infiniteSequence = asAsyncSequence((async function* () { + let i = 0; + while (true) { + yield i++; + } + })()); + const result = await infiniteSequence.isEmpty(); + expect(result).toBeFalsy(); + }); + + it("returns false for non-empty sequences", async () => { + const result = await asyncSequenceOf(1, 2, 3).isEmpty(); + expect(result).toBeFalsy(); + }); + + it("returns true for empty sequences", async () => { + const result = await emptyAsyncSequence().isEmpty(); + expect(result).toBeTruthy(); + }); + + it("returns true for sequences that would be empty", async () => { + const result = await asyncSequenceOf(1, 3) + .filter(async x => x % 2 === 0) + .isEmpty(); + expect(result).toBeTruthy(); + }); + + it("returns false for sequences that would not be empty", async () => { + const result = await asyncSequenceOf(1, 3) + .filter(async x => x % 2 !== 0) + .isEmpty(); + expect(result).toBeFalsy(); + }); +}); + diff --git a/test/operators/async/isNotEmpty.test.ts b/test/operators/async/isNotEmpty.test.ts new file mode 100644 index 0000000..82dba75 --- /dev/null +++ b/test/operators/async/isNotEmpty.test.ts @@ -0,0 +1,39 @@ +import {asyncSequenceOf, emptyAsyncSequence, asAsyncSequence} from "../../../src/sequency"; + +describe("isNotEmpty", () => { + it("returns true for infinite sequences", async () => { + const infiniteSequence = asAsyncSequence((async function* () { + let i = 0; + while (true) { + yield i++; + } + })()); + const result = await infiniteSequence.isNotEmpty(); + expect(result).toBeTruthy(); + }); + + it("returns true for non-empty sequences", async () => { + const result = await asyncSequenceOf(1, 2, 3).isNotEmpty(); + expect(result).toBeTruthy(); + }); + + it("returns false for empty sequences", async () => { + const result = await emptyAsyncSequence().isNotEmpty(); + expect(result).toBeFalsy(); + }); + + it("returns false for sequences that would be empty", async () => { + const result = await asyncSequenceOf(1, 3) + .filter(async x => x % 2 === 0) + .isNotEmpty(); + expect(result).toBeFalsy(); + }); + + it("returns true for sequences that would not be empty", async () => { + const result = await asyncSequenceOf(1, 3) + .filter(async x => x % 2 !== 0) + .isNotEmpty(); + expect(result).toBeTruthy(); + }); +}); + diff --git a/test/isEmpty.test.ts b/test/operators/sync/isEmpty.test.ts similarity index 90% rename from test/isEmpty.test.ts rename to test/operators/sync/isEmpty.test.ts index 79da23b..8d9a77d 100644 --- a/test/isEmpty.test.ts +++ b/test/operators/sync/isEmpty.test.ts @@ -1,4 +1,4 @@ -import { range, sequenceOf } from "../src/Sequence"; +import {range, sequenceOf} from "../../../src/sequency"; describe("isEmpty", () => { it("returns false for infinite sequences", () => { @@ -17,3 +17,4 @@ describe("isEmpty", () => { expect(sequenceOf(1, 3).filter(x => x % 2 !== 0).isEmpty()).toBeFalsy(); }); }); + diff --git a/test/isNotEmpty.test.ts b/test/operators/sync/isNotEmpty.test.ts similarity index 91% rename from test/isNotEmpty.test.ts rename to test/operators/sync/isNotEmpty.test.ts index f7abbef..c88f4f8 100644 --- a/test/isNotEmpty.test.ts +++ b/test/operators/sync/isNotEmpty.test.ts @@ -1,4 +1,4 @@ -import { range, sequenceOf } from "../src/Sequence"; +import {range, sequenceOf} from "../../../src/sequency"; describe("isNotEmpty", () => { it("returns true for infinite sequences", () => { @@ -17,3 +17,4 @@ describe("isNotEmpty", () => { expect(sequenceOf(1, 3).filter(x => x % 2 !== 0).isNotEmpty()).toBeTruthy(); }); }); + From ce8dc6048728d1f702947badc0e22d8a88658066 Mon Sep 17 00:00:00 2001 From: Ilya Gonchar Date: Fri, 21 Nov 2025 01:29:53 +0100 Subject: [PATCH 5/5] fixed readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4071795..85b8412 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ Sequences are **lazily evaluated** to avoid examining all of the input data when ## API documentation -Full API documentation is available at [https://kraken-crypto.github.io/sequency](https://kraken-crypto.github.io/sequency). +Full API documentation is available at [Sequency API docs](https://kraken-crypto.github.io/sequency). Sequency is also fully documented via inline JSDoc comments. When using an IDE like Intellij IDEA or Webstorm the docs are available inline right inside your editor.