1
0

change project structure to remove namespaces

This commit is contained in:
2024-05-11 16:46:47 +02:00
parent 727cdc3b2b
commit 486abefba6
17 changed files with 1201 additions and 1155 deletions

View File

@@ -1,252 +1,17 @@
import { Enumerable } from "./sync.js";
import { asAsyncGenerator, combineAsyncComparers, defaultArrayComparer, identity, isAsyncIterable, operatorCompare, strictEquals } from "./utils.js";
import { createQueue } from "./queue.js";
import { selectionSorter } from "./sorting.js";
import { createAsyncEqualitySet } from "./equality-set.js";
import { createAsyncEqualityMap } from "./equality-map.js";
import { Collector } from "./collector.js";
import { MaybeAsyncPredicate, MaybeAsyncConverter, MaybeAsyncIterable, MaybeAsyncEquater, MaybeAsyncBiConverter, MaybeAsyncAccumulator, MaybeAsyncComparer, Predicate, MaybeAsyncAction, MaybePromise } from "./types.js";
//#region interfaces
export interface AsyncEnumerable<TElement> extends AsyncIterable<Awaited<TElement>> {
iterator(): AsyncIterator<Awaited<TElement>>;
apply<TResult>(pipeline: (enumerable: AsyncEnumerable<TElement>) => TResult): TResult;
count(predicate?: MaybeAsyncPredicate<TElement>): Promise<number>;
nonEnumeratedCount(): Promise<number>;
fastCount(): Promise<number>;
maxCount(): Promise<number>;
select<TResult>(selector: MaybeAsyncConverter<TElement, TResult>): AsyncEnumerable<TResult>;
selectMany<TResult>(selector: MaybeAsyncConverter<TElement, MaybeAsyncIterable<TResult>>): AsyncEnumerable<TResult>;
where(predicate: MaybeAsyncPredicate<TElement>): AsyncEnumerable<TElement>;
groupBy<TKey>(keySelector: MaybeAsyncConverter<TElement, TKey>, elementSelector?: undefined, keyComparer?: MaybeAsyncEquater<TKey>): AsyncEnumerable<GroupedAsyncEnumerable<TKey, TElement>>;
groupBy<TKey, TResult>(keySelector: MaybeAsyncConverter<TElement, TKey>, elementSelector: MaybeAsyncConverter<TElement, TResult>, keyComparer?: MaybeAsyncEquater<TKey>): AsyncEnumerable<GroupedAsyncEnumerable<TKey, TResult>>;
join<TOther, TKey>(iterable: MaybeAsyncIterable<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector?: undefined, keyComparer?: MaybeAsyncEquater<TKey>): AsyncEnumerable<[TElement, TOther]>;
join<TOther, TKey, TResult>(iterable: MaybeAsyncIterable<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector: MaybeAsyncBiConverter<TElement, TOther, TResult>, keyComparer?: MaybeAsyncEquater<TKey>): AsyncEnumerable<TResult>;
groupJoin<TOther, TKey>(iterable: MaybeAsyncIterable<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector?: undefined, keyComparer?: MaybeAsyncEquater<TKey>): AsyncEnumerable<GroupedAsyncEnumerable<TElement, TOther>>;
groupJoin<TOther, TKey, TResult>(iterable: MaybeAsyncIterable<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector: MaybeAsyncBiConverter<TElement, AsyncEnumerable<TOther>, TResult>, keyComparer?: MaybeAsyncEquater<TKey>): AsyncEnumerable<TResult>;
contains(obj: TElement, equater?: MaybeAsyncEquater<TElement>): Promise<boolean>;
sequenceEquals(iterable: MaybeAsyncIterable<TElement>, equater?: MaybeAsyncEquater<TElement>): Promise<boolean>;
append(obj: TElement): AsyncEnumerable<TElement>;
prepend(obj: TElement): AsyncEnumerable<TElement>;
remove(obj: TElement, all?: boolean, equater?: MaybeAsyncEquater<TElement>): AsyncEnumerable<TElement>;
concat(...iterables: MaybeAsyncIterable<TElement>[]): AsyncEnumerable<TElement>;
first(predicate?: MaybeAsyncPredicate<TElement>): Promise<TElement>;
firstOrDefault(predicate?: MaybeAsyncPredicate<TElement>, def?: TElement): Promise<TElement | undefined>;
last(predicate?: MaybeAsyncPredicate<TElement>): Promise<TElement>;
lastOrDefault(predicate?: MaybeAsyncPredicate<TElement>, def?: TElement): Promise<TElement | undefined>;
single(predicate?: MaybeAsyncPredicate<TElement>): Promise<TElement>;
singleOrDefault(predicate?: MaybeAsyncPredicate<TElement>, def?: TElement): Promise<TElement | undefined>;
elementAt(index: number): Promise<TElement>;
elementAtOrDefault(index: number, def?: TElement): Promise<TElement | undefined>;
aggregate(accumulator: MaybeAsyncAccumulator<TElement, TElement>): Promise<TElement>;
aggregate<TAccumulator>(accumulator: MaybeAsyncAccumulator<TElement, TAccumulator>, seed?: TAccumulator): Promise<TAccumulator>;
aggregate<TAccumulator, TResult>(accumulator: MaybeAsyncAccumulator<TElement, TAccumulator>, seed?: TAccumulator, resultSelector?: MaybeAsyncConverter<TAccumulator, TResult>): Promise<TResult>;
min(): Promise<TElement>;
minBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>): Promise<TElement>;
max(): Promise<TElement>;
maxBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>): Promise<TElement>;
order(comparer?: MaybeAsyncComparer<TElement>): AsyncEnumerable<TElement>;
orderBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>): AsyncEnumerable<TElement>;
orderDescending(comparer?: MaybeAsyncComparer<TElement>): AsyncEnumerable<TElement>;
orderByDescending<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>): AsyncEnumerable<TElement>;
distinct(equater?: MaybeAsyncEquater<TElement>): AsyncEnumerable<TElement>;
distinctBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEquater<TBy>): AsyncEnumerable<TElement>;
union(iterable: MaybeAsyncIterable<TElement>, equater?: MaybeAsyncEquater<TElement>): AsyncEnumerable<TElement>;
unionBy<TBy>(iterable: MaybeAsyncIterable<TElement>, selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEquater<TBy>): AsyncEnumerable<TElement>;
except(iterable: MaybeAsyncIterable<TElement>, equater?: MaybeAsyncEquater<TElement>): AsyncEnumerable<TElement>;
exceptBy<TBy>(iterable: MaybeAsyncIterable<TElement>, selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEquater<TBy>): AsyncEnumerable<TElement>;
intersect(iterable: MaybeAsyncIterable<TElement>, equater?: MaybeAsyncEquater<TElement>): AsyncEnumerable<TElement>;
intersectBy<TBy>(iterable: MaybeAsyncIterable<TElement>, selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEquater<TBy>): AsyncEnumerable<TElement>;
all(predicate: MaybeAsyncPredicate<TElement>): Promise<boolean>;
any(predicate: MaybeAsyncPredicate<TElement>): Promise<boolean>;
any(): Promise<boolean>;
none(predicate: Predicate<TElement>): Promise<boolean>;
none(): Promise<boolean>;
skip(n: number): AsyncEnumerable<TElement>;
skipLast(n: number): AsyncEnumerable<TElement>;
skipWhile(condition: MaybeAsyncPredicate<TElement>): AsyncEnumerable<TElement>;
take(n: number): AsyncEnumerable<TElement>;
takeLast(n: number): AsyncEnumerable<TElement>;
takeWhile(condition: MaybeAsyncPredicate<TElement>): AsyncEnumerable<TElement>;
peek(action: MaybeAsyncAction<TElement>): AsyncEnumerable<TElement>;
forEach(action: MaybeAsyncAction<TElement>): Promise<void>;
zip<TOther>(iterable: MaybeAsyncIterable<TOther>): AsyncEnumerable<[TElement, TOther]>;
indexex(): AsyncEnumerable<[number, TElement]>;
reversed(): AsyncEnumerable<TElement>;
chunked(size: number): AsyncEnumerable<TElement[]>;
// random(options?: RandomOptions<TElement>): TElement | undefined;
cached(): AsyncEnumerable<TElement>;
toArray(): Promise<TElement[]>;
toMap<TKey, TValue>(keySelector: MaybeAsyncConverter<TElement, TKey>, valueSelector: MaybeAsyncConverter<TElement, TValue>): Promise<Map<TKey, TValue>>;
toSet(): Promise<Set<TElement>>;
toObject<TKey extends PropertyKey, TValue>(keySelector: MaybeAsyncConverter<TElement, TKey>, valueSelector: MaybeAsyncConverter<TElement, TValue>): Promise<Record<TKey, TValue>>;
collect<TResult>(collector: Collector<TElement, any, TResult>): Promise<TResult>;
}
export interface GroupedAsyncEnumerable<TKey, TElement> extends AsyncEnumerable<TElement> {
get key(): TKey;
}
export interface OrderedAsyncEnumerable<TElement> extends AsyncEnumerable<TElement> {
get comparer(): MaybeAsyncComparer<TElement>;
thenSelf(comparer?: MaybeAsyncComparer<TElement>): OrderedAsyncEnumerable<TElement>;
thenBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>): OrderedAsyncEnumerable<TElement>;
thenSelfDescending(comparer?: MaybeAsyncComparer<TElement>): OrderedAsyncEnumerable<TElement>;
thenByDescending<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>): OrderedAsyncEnumerable<TElement>;
}
//#endregion
//#region wrappers
export namespace AsyncEnumerable {
export function asAsync<T>(enumerable: Enumerable<T>): AsyncEnumerable<T> {
return new WrappedEnumerable(enumerable);
}
export function wrap<T>(iterable: MaybeAsyncIterable<T>): AsyncEnumerable<T> {
if (isAsyncEnumerable<T>(iterable)) {
return iterable;
}
if (isAsyncIterable(iterable)) {
return sequence(iterable);
}
return asAsync(Enumerable.wrap(iterable));
}
export function sequence<T>(iterable: AsyncIterable<T>): AsyncEnumerable<T> {
return new WrappedAsyncIterable(iterable);
}
export function empty<T>(): AsyncEnumerable<T> {
return EmptyAsyncEnumerable.INSTANCE;
}
export function single<T>(obj: T | PromiseLike<T>): AsyncEnumerable<T> {
return new WrappedObjectAsync(obj);
}
export function array<T>(array: (T | PromiseLike<T>)[]): AsyncEnumerable<T> {
return new WrappedArrayAsync(array);
}
export function arrayLike<T>(arrayLike: ArrayLike<(T | PromiseLike<T>)>): AsyncEnumerable<T> {
return new WrappedArrayLikeAsync(arrayLike);
}
export function of<T>(...elements: (T | PromiseLike<T>)[]): AsyncEnumerable<T> {
switch (elements.length) {
case 0:
return empty();
case 1:
return single(elements[0]);
default:
return array(elements);
}
}
export function func<T>(f: () => Promise<T>): AsyncEnumerable<T> {
return new FunctionAsyncEnumerable(f);
}
export function generator<T>(generator: () => AsyncGenerator<T>): AsyncEnumerable<T> {
return new GeneratorAsyncEnumerable(generator);
}
export function range(max: number): AsyncEnumerable<number>
export function range(min: number, max: number): AsyncEnumerable<number>
export function range(min: number, max: number, step: number): AsyncEnumerable<number>
export function range(a: number, b?: number, c?: number): AsyncEnumerable<number> {
if (b === undefined) {
b = a;
a = 0;
}
if (c === undefined) {
c = 1;
}
return new RangeAsyncEnumerable(a, b, c);
}
export function repeat<T>(value: T, count?: number): AsyncEnumerable<T> {
if (count == undefined) {
return new RepeatForeverAsyncEnumerable(value);
}
if (count < 0) {
throw new Error("count < 0");
}
if (count === 0) {
return empty();
}
if (count === 1) {
return new WrappedObjectAsync(value);
}
return new RepeatAsyncEnumerable(value, count);
}
export function isAsyncEnumerable<T = any>(obj: any): obj is AsyncEnumerable<T> {
return obj instanceof AsyncEnumerableMarker;
}
}
//#endregion
//#region implementations
class AsyncEnumerableMarker {
}
import { Collector } from "../collector/types.js";
import { createAsyncEqualityMap } from "../equality-map.js";
import { createAsyncEqualitySet } from "../equality-set.js";
import { createQueue } from "../queue.js";
import { getRandomElementAsync } from "../random/index.js";
import { AsyncRandomOptions } from "../random/types.js";
import { selectionSorter } from "../sorting.js";
import { Enumerable } from "../sync/types.js";
import { MaybeAsyncConverter, MaybeAsyncIterable, MaybeAsyncPredicate, MaybeAsyncEquater, MaybeAsyncBiConverter, MaybeAsyncAccumulator, MaybeAsyncComparer, MaybeAsyncAction, MaybePromise, Predicate } from "../types.js";
import { strictEquals, identity, operatorCompare, asAsyncGenerator, defaultArrayComparer, combineAsyncComparers } from "../utils.js";
import { array, empty, wrap } from "./index.js";
import { AsyncEnumerable, GroupedAsyncEnumerable, OrderedAsyncEnumerable } from "./types.js";
export class AsyncEnumerableMarker { }
export abstract class BaseAsyncEnumerable<TElement> extends AsyncEnumerableMarker implements AsyncEnumerable<TElement> {
[Symbol.asyncIterator]() {
@@ -276,11 +41,11 @@ export abstract class BaseAsyncEnumerable<TElement> extends AsyncEnumerableMarke
}
join<TOther, TKey, TResult>(iterable: MaybeAsyncIterable<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector?: MaybeAsyncBiConverter<TElement, TOther, TResult>, keyComparer?: MaybeAsyncEquater<TKey>): AsyncEnumerable<TResult> {
return new JoinAsyncEnumerable<TElement, TOther, TKey, TResult>(this, AsyncEnumerable.wrap(iterable), firstKeySelector, secondKeySelector, resultSelector, keyComparer);
return new JoinAsyncEnumerable<TElement, TOther, TKey, TResult>(this, wrap(iterable), firstKeySelector, secondKeySelector, resultSelector, keyComparer);
}
groupJoin<TOther, TKey, TResult>(iterable: MaybeAsyncIterable<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector?: MaybeAsyncBiConverter<TElement, AsyncEnumerable<TOther>, TResult>, keyComparer?: MaybeAsyncEquater<TKey>): AsyncEnumerable<TResult> {
return new GroupJoinAsyncEnumerable<TElement, TOther, TKey, TResult>(this, AsyncEnumerable.wrap(iterable), firstKeySelector, secondKeySelector, resultSelector, keyComparer);
return new GroupJoinAsyncEnumerable<TElement, TOther, TKey, TResult>(this, wrap(iterable), firstKeySelector, secondKeySelector, resultSelector, keyComparer);
}
async contains(obj: TElement, equater?: MaybeAsyncEquater<TElement>) {
@@ -302,7 +67,7 @@ export abstract class BaseAsyncEnumerable<TElement> extends AsyncEnumerableMarke
return true;
}
const that = AsyncEnumerable.wrap(iterable);
const that = wrap(iterable);
const thisCount = await this.nonEnumeratedCount();
const thatCount = await that.nonEnumeratedCount();
@@ -356,7 +121,7 @@ export abstract class BaseAsyncEnumerable<TElement> extends AsyncEnumerableMarke
const arr: AsyncEnumerable<TElement>[] = [this];
for (const iterable of iterables) {
arr.push(AsyncEnumerable.wrap(iterable));
arr.push(wrap(iterable));
}
return new ConcatAsyncEnumerable(arr);
@@ -700,27 +465,27 @@ export abstract class BaseAsyncEnumerable<TElement> extends AsyncEnumerableMarke
}
union(iterable: MaybeAsyncIterable<TElement>, equater?: MaybeAsyncEquater<TElement>): AsyncEnumerable<TElement> {
return new UnionAsyncEnumerable<TElement>(this, AsyncEnumerable.wrap(iterable), equater);
return new UnionAsyncEnumerable<TElement>(this, wrap(iterable), equater);
}
unionBy<TBy>(iterable: MaybeAsyncIterable<TElement>, selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEquater<TBy>): AsyncEnumerable<TElement> {
return new UnionByAsyncEnumerable<TElement, TBy>(this, AsyncEnumerable.wrap(iterable), selector, equater);
return new UnionByAsyncEnumerable<TElement, TBy>(this, wrap(iterable), selector, equater);
}
except(iterable: MaybeAsyncIterable<TElement>): AsyncEnumerable<TElement> {
return new ExceptAsyncEnumerable<TElement>(this, AsyncEnumerable.wrap(iterable));
return new ExceptAsyncEnumerable<TElement>(this, wrap(iterable));
}
exceptBy<TBy>(iterable: MaybeAsyncIterable<TElement>, selector: MaybeAsyncConverter<TElement, TBy>): AsyncEnumerable<TElement> {
return new ExceptByAsyncEnumerable<TElement, TBy>(this, AsyncEnumerable.wrap(iterable), selector);
return new ExceptByAsyncEnumerable<TElement, TBy>(this, wrap(iterable), selector);
}
intersect(iterable: MaybeAsyncIterable<TElement>): AsyncEnumerable<TElement> {
return new IntersectAsyncEnumerable<TElement>(this, AsyncEnumerable.wrap(iterable));
return new IntersectAsyncEnumerable<TElement>(this, wrap(iterable));
}
intersectBy<TBy>(iterable: MaybeAsyncIterable<TElement>, selector: MaybeAsyncConverter<TElement, TBy>): AsyncEnumerable<TElement> {
return new IntersectByAsyncEnumerable<TElement, TBy>(this, AsyncEnumerable.wrap(iterable), selector);
return new IntersectByAsyncEnumerable<TElement, TBy>(this, wrap(iterable), selector);
}
async all(predicate: MaybeAsyncPredicate<TElement>) {
@@ -804,7 +569,7 @@ export abstract class BaseAsyncEnumerable<TElement> extends AsyncEnumerableMarke
throw new Error("Cannot take a negative number of elements.");
}
return n === 0 ? AsyncEnumerable.empty<TElement>() : new TakeAsyncEnumerable<TElement>(this, n);
return n === 0 ? empty<TElement>() : new TakeAsyncEnumerable<TElement>(this, n);
}
takeLast(n: number): AsyncEnumerable<TElement> {
@@ -812,7 +577,7 @@ export abstract class BaseAsyncEnumerable<TElement> extends AsyncEnumerableMarke
throw new Error("Cannot take a negative number of elements.");
}
return n === 0 ? AsyncEnumerable.empty<TElement>() : new TakeLastAsyncEnumerable<TElement>(this, n);
return n === 0 ? empty<TElement>() : new TakeLastAsyncEnumerable<TElement>(this, n);
}
takeWhile(predicate: MaybeAsyncPredicate<TElement>): AsyncEnumerable<TElement> {
@@ -829,11 +594,11 @@ export abstract class BaseAsyncEnumerable<TElement> extends AsyncEnumerableMarke
}
}
zip<TOther>(iterable: MaybeAsyncIterable<TOther>): AsyncEnumerable<[TElement, TOther]> {
return new ZippedAsyncEnumerable<TElement, TOther>(this, AsyncEnumerable.wrap(iterable));
zip<TOther>(iterable: MaybeAsyncIterable<TOther>): AsyncEnumerable<[Awaited<TElement>, Awaited<TOther>]> {
return new ZippedAsyncEnumerable<TElement, TOther>(this, wrap(iterable));
}
indexex(): AsyncEnumerable<[number, TElement]> {
indexex(): AsyncEnumerable<[number, Awaited<TElement>]> {
return new IndexedAsyncEnumerable<TElement>(this);
}
@@ -849,6 +614,10 @@ export abstract class BaseAsyncEnumerable<TElement> extends AsyncEnumerableMarke
return new ChunkedAsyncEnumerable<TElement>(this, size);
}
async random(options?: AsyncRandomOptions<TElement> | undefined): Promise<TElement | undefined> {
return (await getRandomElementAsync(this, options)).element;
}
cached(): AsyncEnumerable<TElement> {
return new CacheAsyncEnumerable<TElement>(this);
}
@@ -910,7 +679,7 @@ export abstract class BaseAsyncEnumerable<TElement> extends AsyncEnumerableMarke
}
}
class DelegatedAsyncEnumerable<TElement> extends AsyncEnumerableMarker implements AsyncEnumerable<TElement> {
export class DelegatedAsyncEnumerable<TElement> extends AsyncEnumerableMarker implements AsyncEnumerable<TElement> {
#enumerable: AsyncEnumerable<TElement>;
constructor(enumerable: AsyncEnumerable<TElement>) {
@@ -973,7 +742,7 @@ class DelegatedAsyncEnumerable<TElement> extends AsyncEnumerableMarker implement
return this.#enumerable.groupBy(keySelector, elementSelector, keyComparer);
}
join<TOther, TKey>(iterable: MaybeAsyncIterable<TOther>, firstKeySelector: (obj: TElement) => MaybePromise<TKey>, secondKeySelector: (obj: TOther) => MaybePromise<TKey>, resultSelector?: undefined, keyComparer?: ((first: TKey, second: TKey) => MaybePromise<boolean>) | undefined): AsyncEnumerable<[TElement, TOther]>;
join<TOther, TKey>(iterable: MaybeAsyncIterable<TOther>, firstKeySelector: (obj: TElement) => MaybePromise<TKey>, secondKeySelector: (obj: TOther) => MaybePromise<TKey>, resultSelector?: undefined, keyComparer?: ((first: TKey, second: TKey) => MaybePromise<boolean>) | undefined): AsyncEnumerable<[Awaited<TElement>, Awaited<TOther>]>;
join<TOther, TKey, TResult>(iterable: MaybeAsyncIterable<TOther>, firstKeySelector: (obj: TElement) => MaybePromise<TKey>, secondKeySelector: (obj: TOther) => MaybePromise<TKey>, resultSelector: (first: TElement, second: TOther) => MaybePromise<TResult>, keyComparer?: ((first: TKey, second: TKey) => MaybePromise<boolean>) | undefined): AsyncEnumerable<TResult>;
join(iterable: any, firstKeySelector: any, secondKeySelector: any, resultSelector?: any, keyComparer?: any) {
return this.#enumerable.join(iterable, firstKeySelector, secondKeySelector, resultSelector, keyComparer);
@@ -1160,11 +929,11 @@ class DelegatedAsyncEnumerable<TElement> extends AsyncEnumerableMarker implement
return this.#enumerable.forEach(action);
}
zip<TOther>(iterable: MaybeAsyncIterable<TOther>): AsyncEnumerable<[TElement, TOther]> {
zip<TOther>(iterable: MaybeAsyncIterable<TOther>): AsyncEnumerable<[Awaited<TElement>, Awaited<TOther>]> {
return this.#enumerable.zip(iterable);
}
indexex(): AsyncEnumerable<[number, TElement]> {
indexex(): AsyncEnumerable<[number, Awaited<TElement>]> {
return this.#enumerable.indexex();
}
@@ -1176,6 +945,10 @@ class DelegatedAsyncEnumerable<TElement> extends AsyncEnumerableMarker implement
return this.#enumerable.chunked(size);
}
random(options?: AsyncRandomOptions<TElement> | undefined): Promise<TElement | undefined> {
return this.#enumerable.random(options);
}
cached(): AsyncEnumerable<TElement> {
return this.#enumerable.cached();
}
@@ -1201,7 +974,7 @@ class DelegatedAsyncEnumerable<TElement> extends AsyncEnumerableMarker implement
}
}
class GroupedAsyncEnumerableImpl<TElement, TKey> extends DelegatedAsyncEnumerable<TElement> implements GroupedAsyncEnumerable<TKey, TElement> {
export class GroupedAsyncEnumerableImpl<TElement, TKey> extends DelegatedAsyncEnumerable<TElement> implements GroupedAsyncEnumerable<TKey, TElement> {
readonly #key: TKey;
constructor(key: TKey, grouping: AsyncEnumerable<TElement>) {
@@ -1269,7 +1042,7 @@ abstract class BaseOrderedAsyncEnumerable<TElement> extends BaseAsyncEnumerable<
}
}
class EmptyAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class EmptyAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
static readonly INSTANCE = new EmptyAsyncEnumerable<any>();
override async nonEnumeratedCount() {
@@ -1281,7 +1054,7 @@ class EmptyAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class RangeAsyncEnumerable extends BaseAsyncEnumerable<number> {
export class RangeAsyncEnumerable extends BaseAsyncEnumerable<number> {
readonly #min: number;
readonly #max: number;
readonly #step: number;
@@ -1305,7 +1078,7 @@ class RangeAsyncEnumerable extends BaseAsyncEnumerable<number> {
}
}
class RepeatAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class RepeatAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #value: T;
readonly #count: number;
@@ -1329,7 +1102,7 @@ class RepeatAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class RepeatForeverAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class RepeatForeverAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #value: T;
constructor(value: T) {
@@ -1349,7 +1122,7 @@ class RepeatForeverAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class WrappedObjectAsync<T> extends BaseAsyncEnumerable<T> {
export class WrappedObjectAsync<T> extends BaseAsyncEnumerable<T> {
readonly #obj: T | PromiseLike<T>;
constructor(obj: T | PromiseLike<T>) {
@@ -1367,7 +1140,7 @@ class WrappedObjectAsync<T> extends BaseAsyncEnumerable<T> {
}
}
class WrappedArrayAsync<T> extends BaseAsyncEnumerable<T> {
export class WrappedArrayAsync<T> extends BaseAsyncEnumerable<T> {
readonly #array: (T | PromiseLike<T>)[];
constructor(array: (T | PromiseLike<T>)[]) {
@@ -1385,7 +1158,7 @@ class WrappedArrayAsync<T> extends BaseAsyncEnumerable<T> {
}
}
class WrappedArrayLikeAsync<T> extends BaseAsyncEnumerable<T> {
export class WrappedArrayLikeAsync<T> extends BaseAsyncEnumerable<T> {
readonly #arrayLike: ArrayLike<T | PromiseLike<T>>;
constructor(arrayLike: ArrayLike<T | PromiseLike<T>>) {
@@ -1405,7 +1178,7 @@ class WrappedArrayLikeAsync<T> extends BaseAsyncEnumerable<T> {
}
}
class WrappedAsyncIterable<T> extends BaseAsyncEnumerable<T> {
export class WrappedAsyncIterable<T> extends BaseAsyncEnumerable<T> {
readonly #iterable: AsyncIterable<T>;
constructor(iterable: AsyncIterable<T>) {
@@ -1419,7 +1192,7 @@ class WrappedAsyncIterable<T> extends BaseAsyncEnumerable<T> {
}
}
class GeneratorAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class GeneratorAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #generator: () => AsyncGenerator<T>;
constructor(generator: () => AsyncGenerator<T>) {
@@ -1433,7 +1206,7 @@ class GeneratorAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class FunctionAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class FunctionAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #f: () => MaybePromise<T>;
constructor(f: () => MaybePromise<T>) {
@@ -1453,7 +1226,7 @@ class FunctionAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class WrappedEnumerable<T> extends BaseAsyncEnumerable<T> {
export class WrappedEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #enumerable: Enumerable<T>;
constructor(enumerable: Enumerable<T>) {
@@ -1479,7 +1252,7 @@ class WrappedEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class ConcatAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class ConcatAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #enumerables: Iterable<AsyncEnumerable<T>>;
constructor(enumerables: Iterable<AsyncEnumerable<T>>) {
@@ -1511,7 +1284,7 @@ class ConcatAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class DistinctAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class DistinctAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #enumerable: AsyncEnumerable<T>;
readonly #equater: MaybeAsyncEquater<T> | undefined;
@@ -1533,7 +1306,7 @@ class DistinctAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class DistinctByAsyncEnumerable<T, U> extends BaseAsyncEnumerable<T> {
export class DistinctByAsyncEnumerable<T, U> extends BaseAsyncEnumerable<T> {
readonly #enumerable: AsyncEnumerable<T>;
readonly #selector: MaybeAsyncConverter<T, U>;
readonly #equater: MaybeAsyncEquater<U> | undefined;
@@ -1559,7 +1332,7 @@ class DistinctByAsyncEnumerable<T, U> extends BaseAsyncEnumerable<T> {
}
}
class FilterAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class FilterAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #enumerable: AsyncEnumerable<T>;
readonly #predicate: MaybeAsyncPredicate<T>;
@@ -1579,7 +1352,7 @@ class FilterAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class FlatMapperAsyncEnumerable<T, U> extends BaseAsyncEnumerable<U> {
export class FlatMapperAsyncEnumerable<T, U> extends BaseAsyncEnumerable<U> {
readonly #enumerable: AsyncEnumerable<T>;
readonly #converter: MaybeAsyncConverter<T, MaybeAsyncIterable<U>>;
@@ -1597,7 +1370,7 @@ class FlatMapperAsyncEnumerable<T, U> extends BaseAsyncEnumerable<U> {
}
}
class IndexedAsyncEnumerable<T> extends BaseAsyncEnumerable<[number, T]> {
export class IndexedAsyncEnumerable<T> extends BaseAsyncEnumerable<[number, Awaited<T>]> {
readonly #enumerable: AsyncEnumerable<T>;
constructor(enumerable: AsyncEnumerable<T>) {
@@ -1610,12 +1383,12 @@ class IndexedAsyncEnumerable<T> extends BaseAsyncEnumerable<[number, T]> {
let i = 0;
for await (const obj of this.#enumerable) {
yield [i++, obj] as [number, T];
yield [i++, obj] as [number, Awaited<T>];
}
}
}
class MapperAsyncEnumerable<T, U> extends BaseAsyncEnumerable<U> {
export class MapperAsyncEnumerable<T, U> extends BaseAsyncEnumerable<U> {
readonly #enumerable: AsyncEnumerable<T>;
readonly #converter: MaybeAsyncConverter<T, U>;
@@ -1637,7 +1410,7 @@ class MapperAsyncEnumerable<T, U> extends BaseAsyncEnumerable<U> {
}
}
class SkipWhileAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class SkipWhileAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #enumerable: AsyncEnumerable<T>;
readonly #predicate: MaybeAsyncPredicate<T>;
@@ -1670,7 +1443,7 @@ class SkipWhileAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class SkipLastAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class SkipLastAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #enumerable: AsyncEnumerable<T>;
readonly #n: number;
@@ -1711,7 +1484,7 @@ class SkipLastAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class SkipAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class SkipAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #enumerable: AsyncEnumerable<T>;
readonly #n: number;
@@ -1743,7 +1516,7 @@ class SkipAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class TakeWhileAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class TakeWhileAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #enumerable: AsyncEnumerable<T>;
readonly #predicate: MaybeAsyncPredicate<T>;
@@ -1765,7 +1538,7 @@ class TakeWhileAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class TakeLastAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class TakeLastAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #enumerable: AsyncEnumerable<T>;
readonly #n: number;
@@ -1792,7 +1565,7 @@ class TakeLastAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class TakeAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class TakeAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #enumerable: AsyncEnumerable<T>;
readonly #n: number;
@@ -1825,13 +1598,13 @@ class TakeAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class OrderAsyncEnumerable<T> extends BaseOrderedAsyncEnumerable<T> {
export class OrderAsyncEnumerable<T> extends BaseOrderedAsyncEnumerable<T> {
constructor(enumerable: AsyncEnumerable<T>, descending: boolean, sorter?: MaybeAsyncComparer<T>) {
super(enumerable, sorter ?? defaultArrayComparer, descending);
}
}
class OrderByAsyncEnumerable<T, U> extends BaseOrderedAsyncEnumerable<T> {
export class OrderByAsyncEnumerable<T, U> extends BaseOrderedAsyncEnumerable<T> {
constructor(enumerable: AsyncEnumerable<T>, descending: boolean, selector: MaybeAsyncConverter<T, U>, sorter?: MaybeAsyncComparer<U>) {
super(enumerable, OrderByAsyncEnumerable.#createSorter(selector, sorter), descending);
}
@@ -1842,13 +1615,13 @@ class OrderByAsyncEnumerable<T, U> extends BaseOrderedAsyncEnumerable<T> {
}
}
class ThenOrderAsyncEnumerable<T> extends BaseOrderedAsyncEnumerable<T> {
export class ThenOrderAsyncEnumerable<T> extends BaseOrderedAsyncEnumerable<T> {
constructor(enumerable: OrderedAsyncEnumerable<T>, descending: boolean, sorter?: MaybeAsyncComparer<T>) {
super(enumerable, combineAsyncComparers(enumerable.comparer ?? defaultArrayComparer, sorter ?? defaultArrayComparer), descending);
}
}
class ThenOrderByAsyncEnumerable<T, U> extends BaseOrderedAsyncEnumerable<T> {
export class ThenOrderByAsyncEnumerable<T, U> extends BaseOrderedAsyncEnumerable<T> {
constructor(enumerable: OrderedAsyncEnumerable<T>, descending: boolean, selector: MaybeAsyncConverter<T, U>, sorter?: MaybeAsyncComparer<U>) {
super(enumerable, ThenOrderByAsyncEnumerable.#createCombinedSorter(enumerable.comparer, selector, sorter), descending);
}
@@ -1860,7 +1633,7 @@ class ThenOrderByAsyncEnumerable<T, U> extends BaseOrderedAsyncEnumerable<T> {
}
}
class AppendAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class AppendAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #enumerable: AsyncEnumerable<T>;
readonly #obj: T;
@@ -1882,7 +1655,7 @@ class AppendAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class PrependAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class PrependAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #enumerable: AsyncEnumerable<T>;
readonly #obj: T;
@@ -1904,7 +1677,7 @@ class PrependAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class PeekAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class PeekAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #enumerable: AsyncEnumerable<T>;
readonly #action: MaybeAsyncAction<T>;
@@ -1927,7 +1700,7 @@ class PeekAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class ZippedAsyncEnumerable<T, U> extends BaseAsyncEnumerable<[T, U]> {
export class ZippedAsyncEnumerable<T, U> extends BaseAsyncEnumerable<[Awaited<T>, Awaited<U>]> {
readonly #first: AsyncEnumerable<T>;
readonly #second: AsyncEnumerable<U>;
@@ -1957,12 +1730,12 @@ class ZippedAsyncEnumerable<T, U> extends BaseAsyncEnumerable<[T, U]> {
return;
}
yield [firstNext.value, secondNext.value] as [T, U];
yield [firstNext.value, secondNext.value] as [Awaited<T>, Awaited<U>];
}
}
}
class UnionAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class UnionAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #first: AsyncEnumerable<T>;
readonly #second: AsyncEnumerable<T>;
readonly #equater: MaybeAsyncEquater<T> | undefined;
@@ -1994,7 +1767,7 @@ class UnionAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class UnionByAsyncEnumerable<T, U> extends BaseAsyncEnumerable<T> {
export class UnionByAsyncEnumerable<T, U> extends BaseAsyncEnumerable<T> {
readonly #first: AsyncEnumerable<T>;
readonly #second: AsyncEnumerable<T>;
readonly #selector: MaybeAsyncConverter<T, U>;
@@ -2028,7 +1801,7 @@ class UnionByAsyncEnumerable<T, U> extends BaseAsyncEnumerable<T> {
}
}
class ExceptAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class ExceptAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #first: AsyncEnumerable<T>;
readonly #second: AsyncEnumerable<T>;
readonly #equater: MaybeAsyncEquater<T> | undefined;
@@ -2058,7 +1831,7 @@ class ExceptAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class ExceptByAsyncEnumerable<T, U> extends BaseAsyncEnumerable<T> {
export class ExceptByAsyncEnumerable<T, U> extends BaseAsyncEnumerable<T> {
readonly #first: AsyncEnumerable<T>;
readonly #second: AsyncEnumerable<T>;
readonly #selector: MaybeAsyncConverter<T, U>;
@@ -2090,7 +1863,7 @@ class ExceptByAsyncEnumerable<T, U> extends BaseAsyncEnumerable<T> {
}
}
class IntersectAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class IntersectAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #first: AsyncEnumerable<T>;
readonly #second: AsyncEnumerable<T>;
readonly #equater: MaybeAsyncEquater<T> | undefined;
@@ -2120,7 +1893,7 @@ class IntersectAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class IntersectByAsyncEnumerable<T, U> extends BaseAsyncEnumerable<T> {
export class IntersectByAsyncEnumerable<T, U> extends BaseAsyncEnumerable<T> {
readonly #first: AsyncEnumerable<T>;
readonly #second: AsyncEnumerable<T>;
readonly #selector: MaybeAsyncConverter<T, U>;
@@ -2152,7 +1925,7 @@ class IntersectByAsyncEnumerable<T, U> extends BaseAsyncEnumerable<T> {
}
}
class ReversedAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class ReversedAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #enumerable: AsyncEnumerable<T>;
constructor(enumerable: AsyncEnumerable<T>) {
@@ -2174,7 +1947,7 @@ class ReversedAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class GroupByAsyncEnumerable<TElement, TKey, TResult> extends BaseAsyncEnumerable<GroupedAsyncEnumerable<TKey, TResult>> {
export class GroupByAsyncEnumerable<TElement, TKey, TResult> extends BaseAsyncEnumerable<GroupedAsyncEnumerable<TKey, TResult>> {
readonly #enumerable: AsyncEnumerable<TElement>;
readonly #keySelector: MaybeAsyncConverter<TElement, TKey>;
readonly #elementSelector: MaybeAsyncConverter<TElement, TResult>;
@@ -2204,12 +1977,12 @@ class GroupByAsyncEnumerable<TElement, TKey, TResult> extends BaseAsyncEnumerabl
}
for await (const entry of groupings) {
yield new GroupedAsyncEnumerableImpl(entry[0], AsyncEnumerable.array(entry[1]));
yield new GroupedAsyncEnumerableImpl(entry[0], array(entry[1]));
}
}
}
class ChunkedAsyncEnumerable<T> extends BaseAsyncEnumerable<T[]> {
export class ChunkedAsyncEnumerable<T> extends BaseAsyncEnumerable<T[]> {
readonly #enumerable: AsyncEnumerable<T>;
readonly #size: number;
@@ -2243,7 +2016,7 @@ class ChunkedAsyncEnumerable<T> extends BaseAsyncEnumerable<T[]> {
}
}
class JoinAsyncEnumerable<TOuter, TInner, TKey, TResult> extends BaseAsyncEnumerable<TResult> {
export class JoinAsyncEnumerable<TOuter, TInner, TKey, TResult> extends BaseAsyncEnumerable<TResult> {
readonly #first: AsyncEnumerable<TOuter>;
readonly #second: AsyncEnumerable<TInner>;
readonly #firstKeySelector: MaybeAsyncConverter<TOuter, TKey>;
@@ -2277,7 +2050,7 @@ class JoinAsyncEnumerable<TOuter, TInner, TKey, TResult> extends BaseAsyncEnumer
}
}
class GroupJoinAsyncEnumerable<TOuter, TInner, TKey, TResult> extends BaseAsyncEnumerable<TResult> {
export class GroupJoinAsyncEnumerable<TOuter, TInner, TKey, TResult> extends BaseAsyncEnumerable<TResult> {
readonly #first: AsyncEnumerable<TOuter>;
readonly #second: AsyncEnumerable<TInner>;
readonly #firstKeySelector: MaybeAsyncConverter<TOuter, TKey>;
@@ -2314,12 +2087,12 @@ class GroupJoinAsyncEnumerable<TOuter, TInner, TKey, TResult> extends BaseAsyncE
}
// yield this.#resultSelector(firstObj, this.#second.where(secondObj => this.#keyComparer(firstKey, this.#secondKeySelector(secondObj))));
yield this.#resultSelector(firstObj, AsyncEnumerable.array(secondObjs));
yield this.#resultSelector(firstObj, array(secondObjs));
}
}
}
class RemoveAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class RemoveAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #enumerable: AsyncEnumerable<T>;
readonly #obj: T;
readonly #all: boolean;
@@ -2354,7 +2127,7 @@ class RemoveAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
}
}
class CacheAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
export class CacheAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #enumerable: AsyncEnumerable<T>;
#cache: T[] | undefined;
@@ -2368,20 +2141,3 @@ class CacheAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
yield* this.#cache ??= await this.#enumerable.toArray();
}
}
class AwaitedAsyncEnumerable<T> extends BaseAsyncEnumerable<T> {
readonly #enumerable: AsyncEnumerable<T>;
#cache: T[] | undefined;
constructor(enumerable: AsyncEnumerable<T>) {
super();
this.#enumerable = enumerable;
}
override async *iterator() {
yield* this.#cache ??= await this.#enumerable.toArray();
}
}
//#endregion

101
src/async/index.ts Normal file
View File

@@ -0,0 +1,101 @@
import { wrap as wrapSync } from "../sync/index.js";
import { Enumerable } from "../sync/types.js";
import { MaybeAsyncIterable } from "../types.js";
import { isAsyncIterable } from "../utils.js";
import { WrappedEnumerable, WrappedAsyncIterable, EmptyAsyncEnumerable, WrappedObjectAsync, WrappedArrayAsync, WrappedArrayLikeAsync, FunctionAsyncEnumerable, GeneratorAsyncEnumerable, RangeAsyncEnumerable, RepeatForeverAsyncEnumerable, RepeatAsyncEnumerable, AsyncEnumerableMarker } from "./impl.js";
import { AsyncEnumerable } from "./types.js";
export function asAsync<T>(enumerable: Enumerable<T>): AsyncEnumerable<T> {
return new WrappedEnumerable(enumerable);
}
export function wrap<T>(iterable: MaybeAsyncIterable<T>): AsyncEnumerable<T> {
if (isAsyncEnumerable<T>(iterable)) {
return iterable;
}
if (isAsyncIterable(iterable)) {
return sequence(iterable);
}
return asAsync(wrapSync(iterable));
}
export function sequence<T>(iterable: AsyncIterable<T>): AsyncEnumerable<T> {
return new WrappedAsyncIterable(iterable);
}
export function empty<T>(): AsyncEnumerable<T> {
return EmptyAsyncEnumerable.INSTANCE;
}
export function single<T>(obj: T | PromiseLike<T>): AsyncEnumerable<T> {
return new WrappedObjectAsync(obj);
}
export function array<T>(array: (T | PromiseLike<T>)[]): AsyncEnumerable<T> {
return new WrappedArrayAsync(array);
}
export function arrayLike<T>(arrayLike: ArrayLike<(T | PromiseLike<T>)>): AsyncEnumerable<T> {
return new WrappedArrayLikeAsync(arrayLike);
}
export function of<T>(...elements: (T | PromiseLike<T>)[]): AsyncEnumerable<T> {
switch (elements.length) {
case 0:
return empty();
case 1:
return single(elements[0]);
default:
return array(elements);
}
}
export function func<T>(f: () => Promise<T>): AsyncEnumerable<T> {
return new FunctionAsyncEnumerable(f);
}
export function generator<T>(generator: () => AsyncGenerator<T>): AsyncEnumerable<T> {
return new GeneratorAsyncEnumerable(generator);
}
export function range(max: number): AsyncEnumerable<number>
export function range(min: number, max: number): AsyncEnumerable<number>
export function range(min: number, max: number, step: number): AsyncEnumerable<number>
export function range(a: number, b?: number, c?: number): AsyncEnumerable<number> {
if (b === undefined) {
b = a;
a = 0;
}
if (c === undefined) {
c = 1;
}
return new RangeAsyncEnumerable(a, b, c);
}
export function repeat<T>(value: T, count?: number): AsyncEnumerable<T> {
if (count == undefined) {
return new RepeatForeverAsyncEnumerable(value);
}
if (count < 0) {
throw new Error("count < 0");
}
if (count === 0) {
return empty();
}
if (count === 1) {
return new WrappedObjectAsync(value);
}
return new RepeatAsyncEnumerable(value, count);
}
export function isAsyncEnumerable<T = any>(obj: any): obj is AsyncEnumerable<T> {
return obj instanceof AsyncEnumerableMarker;
}

133
src/async/types.ts Normal file
View File

@@ -0,0 +1,133 @@
import { Collector } from "../collector/types.js";
import { AsyncRandomOptions } from "../random/types.js";
import { MaybeAsyncPredicate, MaybeAsyncConverter, MaybeAsyncIterable, MaybeAsyncEquater, MaybeAsyncBiConverter, MaybeAsyncAccumulator, MaybeAsyncComparer, Predicate, MaybeAsyncAction } from "../types.js";
export interface AsyncEnumerable<TElement> extends AsyncIterable<Awaited<TElement>> {
iterator(): AsyncIterator<Awaited<TElement>>;
apply<TResult>(pipeline: (enumerable: AsyncEnumerable<TElement>) => TResult): TResult;
count(predicate?: MaybeAsyncPredicate<TElement>): Promise<number>;
nonEnumeratedCount(): Promise<number>;
fastCount(): Promise<number>;
maxCount(): Promise<number>;
select<TResult>(selector: MaybeAsyncConverter<TElement, TResult>): AsyncEnumerable<TResult>;
selectMany<TResult>(selector: MaybeAsyncConverter<TElement, MaybeAsyncIterable<TResult>>): AsyncEnumerable<TResult>;
where(predicate: MaybeAsyncPredicate<TElement>): AsyncEnumerable<TElement>;
groupBy<TKey>(keySelector: MaybeAsyncConverter<TElement, TKey>, elementSelector?: undefined, keyComparer?: MaybeAsyncEquater<TKey>): AsyncEnumerable<GroupedAsyncEnumerable<TKey, TElement>>;
groupBy<TKey, TResult>(keySelector: MaybeAsyncConverter<TElement, TKey>, elementSelector: MaybeAsyncConverter<TElement, TResult>, keyComparer?: MaybeAsyncEquater<TKey>): AsyncEnumerable<GroupedAsyncEnumerable<TKey, TResult>>;
join<TOther, TKey>(iterable: MaybeAsyncIterable<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector?: undefined, keyComparer?: MaybeAsyncEquater<TKey>): AsyncEnumerable<[Awaited<TElement>, Awaited<TOther>]>;
join<TOther, TKey, TResult>(iterable: MaybeAsyncIterable<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector: MaybeAsyncBiConverter<TElement, TOther, TResult>, keyComparer?: MaybeAsyncEquater<TKey>): AsyncEnumerable<TResult>;
groupJoin<TOther, TKey>(iterable: MaybeAsyncIterable<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector?: undefined, keyComparer?: MaybeAsyncEquater<TKey>): AsyncEnumerable<GroupedAsyncEnumerable<TElement, TOther>>;
groupJoin<TOther, TKey, TResult>(iterable: MaybeAsyncIterable<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector: MaybeAsyncBiConverter<TElement, AsyncEnumerable<TOther>, TResult>, keyComparer?: MaybeAsyncEquater<TKey>): AsyncEnumerable<TResult>;
contains(obj: TElement, equater?: MaybeAsyncEquater<TElement>): Promise<boolean>;
sequenceEquals(iterable: MaybeAsyncIterable<TElement>, equater?: MaybeAsyncEquater<TElement>): Promise<boolean>;
append(obj: TElement): AsyncEnumerable<TElement>;
prepend(obj: TElement): AsyncEnumerable<TElement>;
remove(obj: TElement, all?: boolean, equater?: MaybeAsyncEquater<TElement>): AsyncEnumerable<TElement>;
concat(...iterables: MaybeAsyncIterable<TElement>[]): AsyncEnumerable<TElement>;
first(predicate?: MaybeAsyncPredicate<TElement>): Promise<TElement>;
firstOrDefault(predicate?: MaybeAsyncPredicate<TElement>, def?: TElement): Promise<TElement | undefined>;
last(predicate?: MaybeAsyncPredicate<TElement>): Promise<TElement>;
lastOrDefault(predicate?: MaybeAsyncPredicate<TElement>, def?: TElement): Promise<TElement | undefined>;
single(predicate?: MaybeAsyncPredicate<TElement>): Promise<TElement>;
singleOrDefault(predicate?: MaybeAsyncPredicate<TElement>, def?: TElement): Promise<TElement | undefined>;
elementAt(index: number): Promise<TElement>;
elementAtOrDefault(index: number, def?: TElement): Promise<TElement | undefined>;
aggregate(accumulator: MaybeAsyncAccumulator<TElement, TElement>): Promise<TElement>;
aggregate<TAccumulator>(accumulator: MaybeAsyncAccumulator<TElement, TAccumulator>, seed?: TAccumulator): Promise<TAccumulator>;
aggregate<TAccumulator, TResult>(accumulator: MaybeAsyncAccumulator<TElement, TAccumulator>, seed?: TAccumulator, resultSelector?: MaybeAsyncConverter<TAccumulator, TResult>): Promise<TResult>;
min(): Promise<TElement>;
minBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>): Promise<TElement>;
max(): Promise<TElement>;
maxBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>): Promise<TElement>;
order(comparer?: MaybeAsyncComparer<TElement>): AsyncEnumerable<TElement>;
orderBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>): AsyncEnumerable<TElement>;
orderDescending(comparer?: MaybeAsyncComparer<TElement>): AsyncEnumerable<TElement>;
orderByDescending<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>): AsyncEnumerable<TElement>;
distinct(equater?: MaybeAsyncEquater<TElement>): AsyncEnumerable<TElement>;
distinctBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEquater<TBy>): AsyncEnumerable<TElement>;
union(iterable: MaybeAsyncIterable<TElement>, equater?: MaybeAsyncEquater<TElement>): AsyncEnumerable<TElement>;
unionBy<TBy>(iterable: MaybeAsyncIterable<TElement>, selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEquater<TBy>): AsyncEnumerable<TElement>;
except(iterable: MaybeAsyncIterable<TElement>, equater?: MaybeAsyncEquater<TElement>): AsyncEnumerable<TElement>;
exceptBy<TBy>(iterable: MaybeAsyncIterable<TElement>, selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEquater<TBy>): AsyncEnumerable<TElement>;
intersect(iterable: MaybeAsyncIterable<TElement>, equater?: MaybeAsyncEquater<TElement>): AsyncEnumerable<TElement>;
intersectBy<TBy>(iterable: MaybeAsyncIterable<TElement>, selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEquater<TBy>): AsyncEnumerable<TElement>;
all(predicate: MaybeAsyncPredicate<TElement>): Promise<boolean>;
any(predicate: MaybeAsyncPredicate<TElement>): Promise<boolean>;
any(): Promise<boolean>;
none(predicate: Predicate<TElement>): Promise<boolean>;
none(): Promise<boolean>;
skip(n: number): AsyncEnumerable<TElement>;
skipLast(n: number): AsyncEnumerable<TElement>;
skipWhile(condition: MaybeAsyncPredicate<TElement>): AsyncEnumerable<TElement>;
take(n: number): AsyncEnumerable<TElement>;
takeLast(n: number): AsyncEnumerable<TElement>;
takeWhile(condition: MaybeAsyncPredicate<TElement>): AsyncEnumerable<TElement>;
peek(action: MaybeAsyncAction<TElement>): AsyncEnumerable<TElement>;
forEach(action: MaybeAsyncAction<TElement>): Promise<void>;
zip<TOther>(iterable: MaybeAsyncIterable<TOther>): AsyncEnumerable<[Awaited<TElement>, Awaited<TOther>]>;
indexex(): AsyncEnumerable<[number, Awaited<TElement>]>;
reversed(): AsyncEnumerable<TElement>;
chunked(size: number): AsyncEnumerable<TElement[]>;
random(options?: AsyncRandomOptions<TElement>): Promise<TElement | undefined>;
cached(): AsyncEnumerable<TElement>;
toArray(): Promise<TElement[]>;
toMap<TKey, TValue>(keySelector: MaybeAsyncConverter<TElement, TKey>, valueSelector: MaybeAsyncConverter<TElement, TValue>): Promise<Map<TKey, TValue>>;
toSet(): Promise<Set<TElement>>;
toObject<TKey extends PropertyKey, TValue>(keySelector: MaybeAsyncConverter<TElement, TKey>, valueSelector: MaybeAsyncConverter<TElement, TValue>): Promise<Record<TKey, TValue>>;
collect<TResult>(collector: Collector<TElement, any, TResult>): Promise<TResult>;
}
export interface GroupedAsyncEnumerable<TKey, TElement> extends AsyncEnumerable<TElement> {
get key(): TKey;
}
export interface OrderedAsyncEnumerable<TElement> extends AsyncEnumerable<TElement> {
get comparer(): MaybeAsyncComparer<TElement>;
thenSelf(comparer?: MaybeAsyncComparer<TElement>): OrderedAsyncEnumerable<TElement>;
thenBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>): OrderedAsyncEnumerable<TElement>;
thenSelfDescending(comparer?: MaybeAsyncComparer<TElement>): OrderedAsyncEnumerable<TElement>;
thenByDescending<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>): OrderedAsyncEnumerable<TElement>;
}

View File

@@ -1,33 +1,6 @@
import { Collector } from "./collector.js";
import { Enumerable } from "./sync.js";
import { asArray } from "./utils.js";
export interface BitArray extends Iterable<boolean> {
readonly length: number;
isFull(): boolean;
isEmpty(): boolean;
get(index: number): boolean;
set(index: number, value: boolean): void;
fill(value: boolean): void;
and(other: BitArray): BitArray;
or(other: BitArray): BitArray;
xor(other: BitArray): BitArray;
not(): BitArray;
contains(other: BitArray): boolean;
intersects(other: BitArray): boolean;
slice(offset: number, length: number): BitArray;
copy(): BitArray;
toArray(): boolean[];
equals(other: BitArray): boolean;
toString(): string;
}
import { join } from "../collector/index.js";
import { arrayLike, sequence } from "../sync/index.js";
import { BitArray } from "./types.js";
const BYTE_SIZE = Uint8Array.BYTES_PER_ELEMENT * 8;
const FULL_BYTE = getMask(BYTE_SIZE);
@@ -81,7 +54,7 @@ function* getBytes(bits: Iterable<boolean>) {
}
}
class BitArrayImpl implements BitArray {
export class BitArrayImpl implements BitArray {
readonly #length: number;
readonly #bits: Uint8Array;
readonly #wholeBytes: number;
@@ -224,16 +197,16 @@ class BitArrayImpl implements BitArray {
this.#ensureSameSize(other);
return other instanceof BitArrayImpl ?
Enumerable.arrayLike(this.#bits).zip(Enumerable.arrayLike(other.#bits)).all(([a, b]) => (a & b) === b) :
Enumerable.sequence(this).zip(Enumerable.sequence(other)).where(([, b]) => b).all(([a, b]) => a && b);
arrayLike(this.#bits).zip(arrayLike(other.#bits)).all(([a, b]) => (a & b) === b) :
sequence(this).zip(sequence(other)).where(([, b]) => b).all(([a, b]) => a && b);
}
public intersects(other: BitArray) {
this.#ensureSameSize(other);
return other instanceof BitArrayImpl ?
Enumerable.arrayLike(this.#bits).zip(Enumerable.arrayLike(other.#bits)).any(([a, b]) => (a & b) !== 0) :
Enumerable.sequence(this).zip(Enumerable.sequence(other)).any(([a, b]) => a && b);
arrayLike(this.#bits).zip(arrayLike(other.#bits)).any(([a, b]) => (a & b) !== 0) :
sequence(this).zip(sequence(other)).any(([a, b]) => a && b);
}
public slice(offset: number, length: number) {
@@ -247,19 +220,19 @@ class BitArrayImpl implements BitArray {
}
public toArray() {
return Enumerable.sequence(this).toArray();
return sequence(this).toArray();
}
public equals(other: BitArray) {
return other === this || other && (other instanceof BitArrayImpl ? Enumerable.arrayLike(this.#bits).sequenceEquals(Enumerable.arrayLike(other.#bits)) : Enumerable.sequence(this).sequenceEquals(Enumerable.sequence(other)));
return other === this || other && (other instanceof BitArrayImpl ? arrayLike(this.#bits).sequenceEquals(arrayLike(other.#bits)) : sequence(this).sequenceEquals(sequence(other)));
}
public toString() {
return Enumerable.sequence(this).select(bit => bit ? '1' : '0').collect(Collector.join());
return sequence(this).select(bit => bit ? '1' : '0').collect(join());
}
}
class EmptyBitArray implements BitArray {
export class EmptyBitArray implements BitArray {
[Symbol.iterator](): Iterator<boolean, any, undefined> {
return {
next: () => ({ done: true, value: undefined })
@@ -353,7 +326,7 @@ class EmptyBitArray implements BitArray {
}
}
class BitArraySlice implements BitArray {
export class BitArraySlice implements BitArray {
readonly #parent: BitArray;
readonly #offset: number;
readonly #length: number;
@@ -465,13 +438,13 @@ class BitArraySlice implements BitArray {
public contains(other: BitArray) {
this.#ensureSameSize(other);
return Enumerable.sequence(this).zip(Enumerable.sequence(other)).where(([, b]) => b).all(([a, b]) => a && b);
return sequence(this).zip(sequence(other)).where(([, b]) => b).all(([a, b]) => a && b);
}
public intersects(other: BitArray) {
this.#ensureSameSize(other);
return Enumerable.sequence(this).zip(Enumerable.sequence(other)).any(([a, b]) => a && b);
return sequence(this).zip(sequence(other)).any(([a, b]) => a && b);
}
public slice(offset: number, length: number) {
@@ -489,43 +462,14 @@ class BitArraySlice implements BitArray {
}
public toArray() {
return Enumerable.sequence(this).toArray();
return sequence(this).toArray();
}
public equals(other: BitArray) {
return other === this || other && Enumerable.sequence(this).sequenceEquals(Enumerable.sequence(other));
return other === this || other && sequence(this).sequenceEquals(sequence(other));
}
public toString() {
return Enumerable.sequence(this).select(bit => bit ? '1' : '0').collect(Collector.join());
}
}
const emptyBitArray = new EmptyBitArray();
export namespace BitArray {
export const EMPTY = emptyBitArray;
export function create(length: number): BitArray {
if (length < 0) {
throw new Error("length < 0");
}
return length === 0 ? EMPTY : new BitArrayImpl(length);
}
export function from(bits: Iterable<boolean>): BitArray {
const arr = asArray(bits);
const result = create(arr.length);
for (let i = 0; i < arr.length; i++) {
result.set(i, arr[i]);
}
return result;
}
export function of(...bits: boolean[]): BitArray {
return from(bits);
return sequence(this).select(bit => bit ? '1' : '0').collect(join());
}
}

29
src/bitarray/index.ts Normal file
View File

@@ -0,0 +1,29 @@
import { asArray } from "../utils.js";
import { EmptyBitArray, BitArrayImpl } from "./impl.js";
import { BitArray } from "./types.js";
const emptyBitArray = new EmptyBitArray();
export const EMPTY = emptyBitArray;
export function create(length: number): BitArray {
if (length < 0) {
throw new Error("length < 0");
}
return length === 0 ? EMPTY : new BitArrayImpl(length);
}
export function from(bits: Iterable<boolean>): BitArray {
const arr = asArray(bits);
const result = create(arr.length);
for (let i = 0; i < arr.length; i++) {
result.set(i, arr[i]);
}
return result;
}
export function of(...bits: boolean[]): BitArray {
return from(bits);
}

26
src/bitarray/types.ts Normal file
View File

@@ -0,0 +1,26 @@
export interface BitArray extends Iterable<boolean> {
readonly length: number;
isFull(): boolean;
isEmpty(): boolean;
get(index: number): boolean;
set(index: number, value: boolean): void;
fill(value: boolean): void;
and(other: BitArray): BitArray;
or(other: BitArray): BitArray;
xor(other: BitArray): BitArray;
not(): BitArray;
contains(other: BitArray): boolean;
intersects(other: BitArray): boolean;
slice(offset: number, length: number): BitArray;
copy(): BitArray;
toArray(): boolean[];
equals(other: BitArray): boolean;
toString(): string;
}

View File

@@ -1,247 +0,0 @@
import { Converter } from "./types.js";
export interface Collector<TElement, TAccumulator, TResult> {
initialize(): TAccumulator;
accumulate(accumulator: TAccumulator, element: TElement): void;
finalize(accumulator: TAccumulator): TResult;
}
export namespace Collector {
class SimpleCollector<TElement, TAccumulator, TResult> implements Collector<TElement, TAccumulator, TResult> {
readonly #initialize: () => TAccumulator;
readonly #accumulate: (accumulator: TAccumulator, element: TElement) => void;
readonly #finalize: (accumulator: TAccumulator) => TResult;
constructor(initialize: () => TAccumulator, accumulate: (accumulator: TAccumulator, element: TElement) => void,
finalize: (accumulator: TAccumulator) => TResult) {
this.#initialize = initialize;
this.#accumulate = accumulate;
this.#finalize = finalize;
}
initialize() {
return this.#initialize();
}
accumulate(accumulator: TAccumulator, element: TElement) {
this.#accumulate(accumulator, element);
}
finalize(accumulator: TAccumulator): TResult {
return this.#finalize(accumulator);
}
}
export function create<TElement, TAccumulator, TResult>(initialize: () => TAccumulator, accumulate: (accumulator: TAccumulator, element: TElement) => void,
finalize: (accumulator: TAccumulator) => TResult): Collector<TElement, TAccumulator, TResult> {
return new SimpleCollector(initialize, accumulate, finalize);
}
class ToArrayCollector<TElement> implements Collector<TElement, TElement[], TElement[]> {
initialize(): TElement[] {
return [];
}
accumulate(accumulator: TElement[], element: TElement) {
accumulator.push(element);
}
finalize(accumulator: TElement[]) {
return accumulator;
}
}
const toArrayCollector = new ToArrayCollector<any>();
export function toArray<TElement>(): Collector<TElement, any, TElement[]> {
return toArrayCollector;
}
class ToObjectCollector<TElement, TKey extends PropertyKey, TValue> implements Collector<TElement, Record<TKey, TValue>, Record<TKey, TValue>> {
readonly #keySelector: Converter<TElement, TKey>;
readonly #valueSelector: Converter<TElement, TValue>;
constructor(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>) {
this.#keySelector = keySelector;
this.#valueSelector = valueSelector;
}
initialize() {
return {} as Record<TKey, TValue>;
}
accumulate(accumulator: Record<TKey, TValue>, element: TElement) {
const key = this.#keySelector(element);
const value = this.#valueSelector(element);
accumulator[key] = value;
}
finalize(accumulator: Record<TKey, TValue>) {
return accumulator;
}
}
export function toObject<TElement, TKey extends PropertyKey, TValue>(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>): Collector<TElement, any, Record<TKey, TValue>> {
return new ToObjectCollector<TElement, TKey, TValue>(keySelector, valueSelector);
}
class ToMapCollector<TElement, TKey, TValue> implements Collector<TElement, Map<TKey, TValue>, Map<TKey, TValue>> {
readonly #keySelector: Converter<TElement, TKey>;
readonly #valueSelector: Converter<TElement, TValue>;
constructor(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>) {
this.#keySelector = keySelector;
this.#valueSelector = valueSelector;
}
initialize() {
return new Map<TKey, TValue>();
}
accumulate(accumulator: Map<TKey, TValue>, element: TElement) {
const key = this.#keySelector(element);
const value = this.#valueSelector(element);
accumulator.set(key, value);
}
finalize(accumulator: Map<TKey, TValue>) {
return accumulator;
}
}
export function toMap<TElement, TKey, TValue>(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>): Collector<TElement, any, Map<TKey, TValue>> {
return new ToMapCollector<TElement, TKey, TValue>(keySelector, valueSelector);
}
class ToSetCollector<TElement> implements Collector<TElement, Set<TElement>, Set<TElement>> {
initialize() {
return new Set<TElement>();
}
accumulate(accumulator: Set<TElement>, element: TElement) {
accumulator.add(element);
}
finalize(accumulator: Set<TElement>) {
return accumulator;
}
}
const toSetCollector = new ToSetCollector<any>();
export function toSet<TElement>(): Collector<TElement, any, Set<TElement>> {
return toSetCollector;
}
class JoinCollector implements Collector<any, any[], string> {
readonly #delimiter: string;
readonly #prefix: string;
readonly #suffix: string;
constructor(delimiter?: string, prefix?: string, suffix?: string) {
this.#delimiter = delimiter ?? "";
this.#prefix = prefix ?? "";
this.#suffix = suffix ?? "";
}
initialize(): any[] {
return [];
}
accumulate(accumulator: any[], element: string) {
accumulator.push(element);
}
finalize(accumulator: any[]) {
return this.#prefix + accumulator.join(this.#delimiter) + this.#suffix;
}
}
export function join(delimiter?: string, prefix?: string, suffix?: string): Collector<any, any, string> {
return new JoinCollector(delimiter, prefix, suffix);
}
class SumCollector implements Collector<number, { sum: number }, number> {
initialize() {
return { sum: 0 };
}
accumulate(accumulator: { sum: number }, element: number) {
accumulator.sum += element;
}
finalize(accumulator: { sum: number }) {
return accumulator.sum;
}
}
const sumCollector = new SumCollector();
export function sum(): Collector<number, any, number> {
return sumCollector;
}
class BigIntSumCollector implements Collector<bigint, { sum: bigint }, bigint> {
initialize() {
return { sum: 0n, };
}
accumulate(accumulator: { sum: bigint }, element: bigint) {
accumulator.sum += element;
}
finalize(accumulator: { sum: bigint }) {
return accumulator.sum;
}
}
const bigintSumCollector = new BigIntSumCollector();
export function bigintSum(): Collector<bigint, any, bigint> {
return bigintSumCollector;
}
class AverageCollector implements Collector<number, { count: number, sum: number }, number> {
initialize() {
return { count: 0, sum: 0 };
}
accumulate(accumulator: { count: number, sum: number }, element: number) {
accumulator.count++;
accumulator.sum += element;
}
finalize(accumulator: { count: number, sum: number }) {
return accumulator.count === 0 ? 0 : accumulator.sum / accumulator.count;
}
}
const averageCollector = new AverageCollector();
export function average(): Collector<number, any, number> {
return averageCollector;
}
class BigIntAverageCollector implements Collector<bigint, { count: number, sum: bigint }, bigint> {
initialize() {
return { count: 0, sum: 0n };
}
accumulate(accumulator: { count: number, sum: bigint }, element: bigint) {
accumulator.count++;
accumulator.sum += element;
}
finalize(accumulator: { count: number, sum: bigint }) {
return accumulator.count === 0 ? 0n : accumulator.sum / BigInt(accumulator.count);
}
}
const bigintAverageCollector = new BigIntAverageCollector();
export function bigintAverage(): Collector<bigint, any, bigint> {
return bigintAverageCollector;
}
}

187
src/collector/impl.ts Normal file
View File

@@ -0,0 +1,187 @@
import { Converter } from "../types.js";
import { Collector } from "./types.js";
export class SimpleCollector<TElement, TAccumulator, TResult> implements Collector<TElement, TAccumulator, TResult> {
readonly #initialize: () => TAccumulator;
readonly #accumulate: (accumulator: TAccumulator, element: TElement) => void;
readonly #finalize: (accumulator: TAccumulator) => TResult;
constructor(initialize: () => TAccumulator, accumulate: (accumulator: TAccumulator, element: TElement) => void,
finalize: (accumulator: TAccumulator) => TResult) {
this.#initialize = initialize;
this.#accumulate = accumulate;
this.#finalize = finalize;
}
initialize() {
return this.#initialize();
}
accumulate(accumulator: TAccumulator, element: TElement) {
this.#accumulate(accumulator, element);
}
finalize(accumulator: TAccumulator): TResult {
return this.#finalize(accumulator);
}
}
export class ToArrayCollector<TElement> implements Collector<TElement, TElement[], TElement[]> {
initialize(): TElement[] {
return [];
}
accumulate(accumulator: TElement[], element: TElement) {
accumulator.push(element);
}
finalize(accumulator: TElement[]) {
return accumulator;
}
}
export class ToObjectCollector<TElement, TKey extends PropertyKey, TValue> implements Collector<TElement, Record<TKey, TValue>, Record<TKey, TValue>> {
readonly #keySelector: Converter<TElement, TKey>;
readonly #valueSelector: Converter<TElement, TValue>;
constructor(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>) {
this.#keySelector = keySelector;
this.#valueSelector = valueSelector;
}
initialize() {
return {} as Record<TKey, TValue>;
}
accumulate(accumulator: Record<TKey, TValue>, element: TElement) {
const key = this.#keySelector(element);
const value = this.#valueSelector(element);
accumulator[key] = value;
}
finalize(accumulator: Record<TKey, TValue>) {
return accumulator;
}
}
export class ToMapCollector<TElement, TKey, TValue> implements Collector<TElement, Map<TKey, TValue>, Map<TKey, TValue>> {
readonly #keySelector: Converter<TElement, TKey>;
readonly #valueSelector: Converter<TElement, TValue>;
constructor(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>) {
this.#keySelector = keySelector;
this.#valueSelector = valueSelector;
}
initialize() {
return new Map<TKey, TValue>();
}
accumulate(accumulator: Map<TKey, TValue>, element: TElement) {
const key = this.#keySelector(element);
const value = this.#valueSelector(element);
accumulator.set(key, value);
}
finalize(accumulator: Map<TKey, TValue>) {
return accumulator;
}
}
export class ToSetCollector<TElement> implements Collector<TElement, Set<TElement>, Set<TElement>> {
initialize() {
return new Set<TElement>();
}
accumulate(accumulator: Set<TElement>, element: TElement) {
accumulator.add(element);
}
finalize(accumulator: Set<TElement>) {
return accumulator;
}
}
export class JoinCollector implements Collector<any, any[], string> {
readonly #delimiter: string;
readonly #prefix: string;
readonly #suffix: string;
constructor(delimiter?: string, prefix?: string, suffix?: string) {
this.#delimiter = delimiter ?? "";
this.#prefix = prefix ?? "";
this.#suffix = suffix ?? "";
}
initialize(): any[] {
return [];
}
accumulate(accumulator: any[], element: string) {
accumulator.push(element);
}
finalize(accumulator: any[]) {
return this.#prefix + accumulator.join(this.#delimiter) + this.#suffix;
}
}
export class SumCollector implements Collector<number, { sum: number }, number> {
initialize() {
return { sum: 0 };
}
accumulate(accumulator: { sum: number }, element: number) {
accumulator.sum += element;
}
finalize(accumulator: { sum: number }) {
return accumulator.sum;
}
}
export class BigIntSumCollector implements Collector<bigint, { sum: bigint }, bigint> {
initialize() {
return { sum: 0n, };
}
accumulate(accumulator: { sum: bigint }, element: bigint) {
accumulator.sum += element;
}
finalize(accumulator: { sum: bigint }) {
return accumulator.sum;
}
}
export class AverageCollector implements Collector<number, { count: number, sum: number }, number> {
initialize() {
return { count: 0, sum: 0 };
}
accumulate(accumulator: { count: number, sum: number }, element: number) {
accumulator.count++;
accumulator.sum += element;
}
finalize(accumulator: { count: number, sum: number }) {
return accumulator.count === 0 ? 0 : accumulator.sum / accumulator.count;
}
}
export class BigIntAverageCollector implements Collector<bigint, { count: number, sum: bigint }, bigint> {
initialize() {
return { count: 0, sum: 0n };
}
accumulate(accumulator: { count: number, sum: bigint }, element: bigint) {
accumulator.count++;
accumulator.sum += element;
}
finalize(accumulator: { count: number, sum: bigint }) {
return accumulator.count === 0 ? 0n : accumulator.sum / BigInt(accumulator.count);
}
}

56
src/collector/index.ts Normal file
View File

@@ -0,0 +1,56 @@
import { Converter } from "../types.js";
import { SimpleCollector, ToArrayCollector, ToObjectCollector, ToMapCollector, ToSetCollector, JoinCollector, SumCollector, BigIntSumCollector, AverageCollector, BigIntAverageCollector } from "./impl.js";
import { Collector } from "./types.js";
export function create<TElement, TAccumulator, TResult>(initialize: () => TAccumulator, accumulate: (accumulator: TAccumulator, element: TElement) => void,
finalize: (accumulator: TAccumulator) => TResult): Collector<TElement, TAccumulator, TResult> {
return new SimpleCollector(initialize, accumulate, finalize);
}
const toArrayCollector = new ToArrayCollector<any>();
export function toArray<TElement>(): Collector<TElement, any, TElement[]> {
return toArrayCollector;
}
export function toObject<TElement, TKey extends PropertyKey, TValue>(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>): Collector<TElement, any, Record<TKey, TValue>> {
return new ToObjectCollector<TElement, TKey, TValue>(keySelector, valueSelector);
}
export function toMap<TElement, TKey, TValue>(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>): Collector<TElement, any, Map<TKey, TValue>> {
return new ToMapCollector<TElement, TKey, TValue>(keySelector, valueSelector);
}
const toSetCollector = new ToSetCollector<any>();
export function toSet<TElement>(): Collector<TElement, any, Set<TElement>> {
return toSetCollector;
}
export function join(delimiter?: string, prefix?: string, suffix?: string): Collector<any, any, string> {
return new JoinCollector(delimiter, prefix, suffix);
}
const sumCollector = new SumCollector();
export function sum(): Collector<number, any, number> {
return sumCollector;
}
const bigintSumCollector = new BigIntSumCollector();
export function bigintSum(): Collector<bigint, any, bigint> {
return bigintSumCollector;
}
const averageCollector = new AverageCollector();
export function average(): Collector<number, any, number> {
return averageCollector;
}
const bigintAverageCollector = new BigIntAverageCollector();
export function bigintAverage(): Collector<bigint, any, bigint> {
return bigintAverageCollector;
}

5
src/collector/types.ts Normal file
View File

@@ -0,0 +1,5 @@
export interface Collector<TElement, TAccumulator, TResult> {
initialize(): TAccumulator;
accumulate(accumulator: TAccumulator, element: TElement): void;
finalize(accumulator: TAccumulator): TResult;
}

View File

@@ -1,4 +1,12 @@
export { BaseEnumerable, Enumerable, GroupedEnumerable, OrderedEnumerable } from "./sync.js";
export { AsyncEnumerable, BaseAsyncEnumerable, GroupedAsyncEnumerable, OrderedAsyncEnumerable } from "./async.js";
export { Collector } from "./collector.js";
export { Random, RandomOptions } from "./random.js";
export { BaseEnumerable, DelegatedEnumerable } from "./sync/impl.js";
export * as Enumerables from "./sync/index.js";
export * from "./sync/types.js";
export { BaseAsyncEnumerable, DelegatedAsyncEnumerable } from "./async/impl.js";
export * as AsyncEnumerables from "./async/index.js";
export * from "./async/types.js";
export * as Collectors from "./collector/index.js";
export * from "./collector/types.js";
export * as BitArrays from "./bitarray/index.js";
export * from "./bitarray/types.js";
export * as Random from "./random/index.js";
export * from "./random/types.js";

View File

@@ -1,136 +0,0 @@
import { BitArray } from "./bitarray.js";
import { asArray } from "./utils.js";
export type ElementPredicate<T = any> = (index: number, obj: T) => boolean;
export type ElementWeight<T = any> = (index: number, obj: T) => number;
export type RandomGenerator = () => number;
export interface RandomOptions<T = any> {
predicate?: ElementPredicate<T>;
weight?: ElementWeight<T>;
random?: RandomGenerator;
};
export namespace Random {
export const alwaysTrue: ElementPredicate = () => true;
export const weightOfOne: ElementWeight = () => 1.0;
export const mathRandom: RandomGenerator = () => Math.random();
const defaultOptions = Object.freeze<Required<RandomOptions>>({
predicate: alwaysTrue,
weight: weightOfOne,
random: mathRandom
});
function mergeOptions<T>(first: RandomOptions<T> | undefined, second: RandomOptions<T> | undefined): RandomOptions<T> | undefined {
if (!first) {
return second;
}
if (!second) {
return first;
}
const firstPredicate = first.predicate;
const secondPredicate = second.predicate;
return {
predicate: firstPredicate ? secondPredicate ? (i, o) => firstPredicate(i, o) && secondPredicate(i, o) : firstPredicate : secondPredicate,
weight: first.weight ?? second.weight,
random: first.random ?? second.random
};
}
function withDefaultOptions<T>(options: RandomOptions<T> | undefined): Required<RandomOptions<T>> {
if (!options || options === defaultOptions) {
return defaultOptions;
}
return {
predicate: options.predicate ?? defaultOptions.predicate,
weight: options.weight ?? defaultOptions.weight,
random: options.random ?? defaultOptions.random
};
}
function _getRandomElement<T>(sequence: Iterable<T>, options: Required<RandomOptions<T>>) {
const { predicate, weight, random } = options;
let result: T | undefined = undefined;
let resultIndex = -1;
let index = 0;
let weightAcc = 0.0;
for (const element of sequence) {
const currentIndex = index++;
if (predicate(currentIndex, element)) {
const w = weight(currentIndex, element);
if (w <= 0.0) {
continue;
}
weightAcc += w;
if (random() * weightAcc < w) {
result = element;
resultIndex = currentIndex;
}
}
}
return { element: result, index: resultIndex };
}
export function getRandomElement<T>(sequence: Iterable<T>, options?: RandomOptions<T>) {
return _getRandomElement(sequence, withDefaultOptions(options));
}
export class RandomPicker<T> {
readonly #elements: Iterable<T>;
readonly #flags: BitArray;
readonly #options: Required<RandomOptions<T>>;
public constructor(elements: Iterable<T>, length: number, options?: RandomOptions<T>) {
this.#elements = elements;
this.#flags = BitArray.create(length);
this.#options = withDefaultOptions(mergeOptions({ predicate: i => this.#flags.get(i) }, options));
this.reset();
}
public static from<T>(iterable: Iterable<T>, options?: RandomOptions<T>) {
const arr = asArray(iterable);
return new this<T>(arr, arr.length, options);
}
public static of<T>(options?: RandomOptions<T>, ...values: T[]) {
return new this<T>(values, values.length, options);
}
public get state() {
return this.#flags;
}
public reset() {
this.#flags.fill(true);
}
public next() {
const result = _getRandomElement(this.#elements, this.#options);
if (result.index < 0) {
this.reset();
} else {
this.#flags.set(result.index, false);
if (this.#flags.isEmpty()) {
this.reset();
}
}
return result.element;
}
}
}

162
src/random/index.ts Normal file
View File

@@ -0,0 +1,162 @@
import { create as createBitArray } from "../bitarray/index.js";
import { BitArray } from "../bitarray/types.js";
import { asArray } from "../utils.js";
import { AsyncRandomOptions, ElementPredicate, ElementWeight, RandomGenerator, RandomOptions } from "./types.js";
export const alwaysTrue: ElementPredicate = () => true;
export const weightOfOne: ElementWeight = () => 1.0;
export const mathRandom: RandomGenerator = () => Math.random();
const defaultOptions = Object.freeze<Required<RandomOptions>>({
predicate: alwaysTrue,
weight: weightOfOne,
random: mathRandom
});
function mergeOptions<T>(first: RandomOptions<T> | undefined, second: RandomOptions<T> | undefined): RandomOptions<T> | undefined {
if (!first) {
return second;
}
if (!second) {
return first;
}
const firstPredicate = first.predicate;
const secondPredicate = second.predicate;
return {
predicate: firstPredicate ? secondPredicate ? (i, o) => firstPredicate(i, o) && secondPredicate(i, o) : firstPredicate : secondPredicate,
weight: first.weight ?? second.weight,
random: first.random ?? second.random
};
}
function withDefaultOptions<T>(options: RandomOptions<T> | undefined): Required<RandomOptions<T>>;
function withDefaultOptions<T>(options: AsyncRandomOptions<T> | undefined): Required<AsyncRandomOptions<T>>;
function withDefaultOptions<T>(options: RandomOptions<T> | AsyncRandomOptions<T> | undefined): Required<RandomOptions<T> | AsyncRandomOptions<T>> {
if (!options || options === defaultOptions) {
return defaultOptions;
}
return {
predicate: options.predicate ?? defaultOptions.predicate,
weight: options.weight ?? defaultOptions.weight,
random: options.random ?? defaultOptions.random
};
}
function _getRandomElement<T>(sequence: Iterable<T>, options: Required<RandomOptions<T>>) {
const { predicate, weight, random } = options;
let result: T | undefined = undefined;
let resultIndex = -1;
let index = 0;
let weightAcc = 0.0;
for (const element of sequence) {
const currentIndex = index++;
if (predicate(currentIndex, element)) {
const w = weight(currentIndex, element);
if (w <= 0.0) {
continue;
}
weightAcc += w;
if (random() * weightAcc < w) {
result = element;
resultIndex = currentIndex;
}
}
}
return { element: result, index: resultIndex };
}
export function getRandomElement<T>(sequence: Iterable<T>, options?: RandomOptions<T>) {
return _getRandomElement(sequence, withDefaultOptions(options));
}
async function _getRandomElementAsync<T>(sequence: AsyncIterable<T>, options: Required<AsyncRandomOptions<T>>) {
const { predicate, weight, random } = options;
let result: T | undefined = undefined;
let resultIndex = -1;
let index = 0;
let weightAcc = 0.0;
for await (const element of sequence) {
const currentIndex = index++;
if (await predicate(currentIndex, element)) {
const w = await weight(currentIndex, element);
if (w <= 0.0) {
continue;
}
weightAcc += w;
if (random() * weightAcc < w) {
result = element;
resultIndex = currentIndex;
}
}
}
return { element: result, index: resultIndex };
}
export async function getRandomElementAsync<T>(sequence: AsyncIterable<T>, options?: AsyncRandomOptions<T>) {
return await _getRandomElementAsync(sequence, withDefaultOptions(options));
}
export class RandomPicker<T> {
readonly #elements: Iterable<T>;
readonly #flags: BitArray;
readonly #options: Required<RandomOptions<T>>;
public constructor(elements: Iterable<T>, length: number, options?: RandomOptions<T>) {
this.#elements = elements;
this.#flags = createBitArray(length);
this.#options = withDefaultOptions(mergeOptions({ predicate: i => this.#flags.get(i) }, options));
this.reset();
}
public static from<T>(iterable: Iterable<T>, options?: RandomOptions<T>) {
const arr = asArray(iterable);
return new this<T>(arr, arr.length, options);
}
public static of<T>(options?: RandomOptions<T>, ...values: T[]) {
return new this<T>(values, values.length, options);
}
public get state() {
return this.#flags;
}
public reset() {
this.#flags.fill(true);
}
public next() {
const result = _getRandomElement(this.#elements, this.#options);
if (result.index < 0) {
this.reset();
} else {
this.#flags.set(result.index, false);
if (this.#flags.isEmpty()) {
this.reset();
}
}
return result.element;
}
}

20
src/random/types.ts Normal file
View File

@@ -0,0 +1,20 @@
import { MaybeAsyncFunction } from "../types.js";
export type ElementPredicate<T = any> = (index: number, obj: T) => boolean;
export type ElementWeight<T = any> = (index: number, obj: T) => number;
export type RandomGenerator = () => number;
export interface RandomOptions<T = any> {
predicate?: ElementPredicate<T>;
weight?: ElementWeight<T>;
random?: RandomGenerator;
};
export type MaybeAsyncElementPredicate<T = any> = MaybeAsyncFunction<ElementPredicate<T>>;
export type MaybeAsyncElementWeight<T = any> = MaybeAsyncFunction<ElementWeight<T>>;
export interface AsyncRandomOptions<T = any> {
predicate?: MaybeAsyncElementPredicate<T>;
weight?: MaybeAsyncElementWeight<T>;
random?: RandomGenerator;
};

View File

@@ -1,293 +1,15 @@
import { createEqualitySet } from "./equality-set.js";
import { createEqualityMap } from "./equality-map.js";
import { RandomGenerator, RandomOptions, Random } from "./random.js";
import { createQueue } from "./queue.js";
import { Collector } from "./collector.js";
import { combineComparers, defaultArrayComparer, identity, operatorCompare, reverseComparer, strictEquals, wrapAsIterable } from "./utils.js";
import { Predicate, Converter, FilterPredicate, Equater, BiConverter, Accumulator, Comparer, Action } from "./types.js";
export interface Enumerable<TElement> extends Iterable<TElement> {
iterator(): Iterator<TElement>;
apply<TResult>(pipeline: (enumerable: Enumerable<TElement>) => TResult): TResult;
count(predicate?: Predicate<TElement>): number;
nonEnumeratedCount(): number;
fastCount(): number;
maxCount(): number;
select<TResult>(selector: Converter<TElement, TResult>): Enumerable<TResult>;
selectMany<TResult>(selector: Converter<TElement, Iterable<TResult>>): Enumerable<TResult>;
where<TFiltered extends TElement>(predicate: FilterPredicate<TElement, TFiltered>): Enumerable<TFiltered>;
where(predicate: Predicate<TElement>): Enumerable<TElement>;
groupBy<TKey>(keySelector: Converter<TElement, TKey>, elementSelector?: undefined, keyComparer?: Equater<TKey>): Enumerable<GroupedEnumerable<TKey, TElement>>;
groupBy<TKey, TResult>(keySelector: Converter<TElement, TKey>, elementSelector: Converter<TElement, TResult>, keyComparer?: Equater<TKey>): Enumerable<GroupedEnumerable<TKey, TResult>>;
join<TOther, TKey>(iterable: Iterable<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector?: undefined, keyComparer?: Equater<TKey>): Enumerable<[TElement, TOther]>;
join<TOther, TKey, TResult>(iterable: Iterable<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector: BiConverter<TElement, TOther, TResult>, keyComparer?: Equater<TKey>): Enumerable<TResult>;
groupJoin<TOther, TKey>(iterable: Iterable<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector?: undefined, keyComparer?: Equater<TKey>): Enumerable<GroupedEnumerable<TElement, TOther>>;
groupJoin<TOther, TKey, TResult>(iterable: Iterable<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector: BiConverter<TElement, Enumerable<TOther>, TResult>, keyComparer?: Equater<TKey>): Enumerable<TResult>;
contains(obj: TElement, equater?: Equater<TElement>): boolean;
sequenceEquals(iterable: Iterable<TElement>, equater?: Equater<TElement>): boolean;
append(obj: TElement): Enumerable<TElement>;
prepend(obj: TElement): Enumerable<TElement>;
remove(obj: TElement, all?: boolean, equater?: Equater<TElement>): Enumerable<TElement>;
concat(...iterables: Iterable<TElement>[]): Enumerable<TElement>;
first(predicate?: Predicate<TElement>): TElement;
firstOrDefault(predicate?: Predicate<TElement>, def?: TElement): TElement | undefined;
last(predicate?: Predicate<TElement>): TElement;
lastOrDefault(predicate?: Predicate<TElement>, def?: TElement): TElement | undefined;
single(predicate?: Predicate<TElement>): TElement;
singleOrDefault(predicate?: Predicate<TElement>, def?: TElement): TElement | undefined;
elementAt(index: number): TElement;
elementAtOrDefault(index: number, def?: TElement): TElement | undefined;
aggregate(accumulator: Accumulator<TElement, TElement>): TElement;
aggregate<TAccumulator>(accumulator: Accumulator<TElement, TAccumulator>, seed?: TAccumulator): TAccumulator;
aggregate<TAccumulator, TResult>(accumulator: Accumulator<TElement, TAccumulator>, seed?: TAccumulator, resultSelector?: Converter<TAccumulator, TResult>): TResult;
min(comparer?: Comparer<TElement>): TElement;
minBy<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): TElement;
max(comparer?: Comparer<TElement>): TElement;
maxBy<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): TElement;
order(comparer?: Comparer<TElement>): OrderedEnumerable<TElement>;
orderBy<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): OrderedEnumerable<TElement>;
orderDescending(comparer?: Comparer<TElement>): OrderedEnumerable<TElement>;
orderByDescending<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): OrderedEnumerable<TElement>;
distinct(equater?: Equater<TElement>): Enumerable<TElement>;
distinctBy<TBy>(selector: Converter<TElement, TBy>, equater?: Equater<TBy>): Enumerable<TElement>;
union(iterable: Iterable<TElement>, equater?: Equater<TElement>): Enumerable<TElement>;
unionBy<TBy>(iterable: Iterable<TElement>, selector: Converter<TElement, TBy>, equater?: Equater<TBy>): Enumerable<TElement>;
except(iterable: Iterable<TElement>, equater?: Equater<TElement>): Enumerable<TElement>;
exceptBy<TBy>(iterable: Iterable<TElement>, selector: Converter<TElement, TBy>, equater?: Equater<TBy>): Enumerable<TElement>;
intersect(iterable: Iterable<TElement>, equater?: Equater<TElement>): Enumerable<TElement>;
intersectBy<TBy>(iterable: Iterable<TElement>, selector: Converter<TElement, TBy>, equater?: Equater<TBy>): Enumerable<TElement>;
all(predicate: Predicate<TElement>): boolean;
any(predicate: Predicate<TElement>): boolean;
any(): boolean;
none(predicate: Predicate<TElement>): boolean;
none(): boolean;
skip(n: number): Enumerable<TElement>;
skipLast(n: number): Enumerable<TElement>;
skipWhile(condition: Predicate<TElement>): Enumerable<TElement>;
take(n: number): Enumerable<TElement>;
takeLast(n: number): Enumerable<TElement>;
takeWhile(condition: Predicate<TElement>): Enumerable<TElement>;
peek(action: Action<TElement>): Enumerable<TElement>;
forEach(action: Action<TElement>): void;
zip<TOther>(iterable: Iterable<TOther>): Enumerable<[TElement, TOther]>;
indexed(): Enumerable<[number, TElement]>;
reversed(): Enumerable<TElement>;
chunked(size: number): Enumerable<TElement[]>;
random(options?: RandomOptions<TElement>): TElement | undefined;
cached(): Enumerable<TElement>;
asArray(): TElement[];
toArray(): TElement[];
toMap<TKey, TValue>(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>): Map<TKey, TValue>;
toSet(): Set<TElement>;
toObject<TKey extends PropertyKey, TValue>(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>): Record<TKey, TValue>;
collect<TResult>(collector: Collector<TElement, any, TResult>): TResult;
}
export interface GroupedEnumerable<TKey, TElement> extends Enumerable<TElement> {
get key(): TKey;
}
export interface OrderedEnumerable<TElement> extends Enumerable<TElement> {
get comparer(): Comparer<TElement> | undefined;
thenSelf(comparer?: Comparer<TElement>): OrderedEnumerable<TElement>;
thenBy<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): OrderedEnumerable<TElement>;
thenSelfDescending(comparer?: Comparer<TElement>): OrderedEnumerable<TElement>;
thenByDescending<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): OrderedEnumerable<TElement>;
}
export namespace Enumerable {
export function wrap<T>(iterable: Iterable<T>): Enumerable<T> {
if (isEnumerable<T>(iterable)) {
return iterable;
}
if (Array.isArray(iterable)) {
return array(iterable);
}
if (iterable instanceof Set) {
return set<T>(iterable);
}
if (iterable instanceof Map) {
return map(iterable) as unknown as Enumerable<T>;
}
return sequence(iterable);
}
export function sequence<T>(iterable: Iterable<T>): Enumerable<T> {
return new WrappedIterable(iterable);
}
export function empty<T>(): Enumerable<T> {
return EmptyEnumerable.INSTANCE;
}
export function single<T>(obj: T): Enumerable<T> {
return new WrappedObject(obj);
}
export function array<T>(array: T[]): Enumerable<T> {
return new WrappedArray(array);
}
export function arrayLike<T>(arrayLike: ArrayLike<T>): Enumerable<T> {
return new WrappedArrayLike(arrayLike);
}
export function set<T>(set: Set<T>): Enumerable<T> {
return new WrappedSet(set);
}
export function map<K, V>(map: Map<K, V>): Enumerable<[K, V]> {
return new WrappedMap(map);
}
export function of<T>(...elements: T[]): Enumerable<T> {
switch (elements.length) {
case 0:
return empty();
case 1:
return single(elements[0]);
default:
return array(elements);
}
}
export function ofPropertyKeys<T extends PropertyKey>(...elements: T[]): Enumerable<T> {
return of(...elements);
}
export function entries<T>(o: Record<string, T> | ArrayLike<T>): Enumerable<[string, T]> {
return array(Object.entries(o));
}
export function keys(o: object): Enumerable<string> {
return array(Object.keys(o));
}
export function func<T>(f: () => T): Enumerable<T> {
return new FunctionEnumerable(f);
}
export function generator<T>(generator: () => Iterable<T>): Enumerable<T> {
return new GeneratorEnumerable(generator);
}
export function range(max: number): Enumerable<number>
export function range(min: number, max: number): Enumerable<number>
export function range(min: number, max: number, step: number): Enumerable<number>
export function range(a: number, b?: number, c?: number): Enumerable<number> {
if (b === undefined) {
b = a;
a = 0;
}
if (c === undefined) {
c = 1;
}
return new RangeEnumerable(a, b, c);
}
export function bigintRange(max: bigint): Enumerable<bigint>
export function bigintRange(min: bigint, max: bigint): Enumerable<bigint>
export function bigintRange(min: bigint, max: bigint, step: bigint): Enumerable<bigint>
export function bigintRange(a: bigint, b?: bigint, c?: bigint): Enumerable<bigint> {
if (b === undefined) {
b = a;
a = 0n;
}
if (c === undefined) {
c = 1n;
}
return new BigIntRangeEnumerable(a, b, c);
}
export function repeat<T>(value: T, count?: number): Enumerable<T> {
if (count == undefined) {
return new RepeatForeverEnumerable(value);
}
if (count < 0) {
throw new RangeError();
}
if (count === 0) {
return empty();
}
if (count === 1) {
return new WrappedObject(value);
}
return new RepeatEnumerable(value, count);
}
export function randomSequence(random?: RandomGenerator): Enumerable<number> {
return new FunctionEnumerable(random ?? Random.mathRandom);
}
export function concat<T>(...enumerables: Enumerable<T>[]): Enumerable<T> {
return new ConcatEnumerable(enumerables);
}
export function isEnumerable<T = any>(obj: any): obj is Enumerable<T> {
return obj instanceof EnumerableMarker;
}
}
//#region enumerable implementation
class EnumerableMarker {
}
import { Collector } from "../collector/types.js";
import { createEqualityMap } from "../equality-map.js";
import { createEqualitySet } from "../equality-set.js";
import { createQueue } from "../queue.js";
import { getRandomElement } from "../random/index.js";
import { RandomOptions } from "../random/types.js";
import { Converter, FilterPredicate, Equater, BiConverter, Predicate, Accumulator, Comparer, Action } from "../types.js";
import { strictEquals, identity, operatorCompare, reverseComparer, wrapAsIterable, defaultArrayComparer, combineComparers } from "../utils.js";
import { array, empty, wrap } from "./index.js";
import { Enumerable, GroupedEnumerable, OrderedEnumerable } from "./types.js";
export class EnumerableMarker { }
export abstract class BaseEnumerable<TElement> extends EnumerableMarker implements Enumerable<TElement> {
[Symbol.iterator]() {
@@ -317,11 +39,11 @@ export abstract class BaseEnumerable<TElement> extends EnumerableMarker implemen
}
join<TOther, TKey, TResult>(iterable: Iterable<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector?: BiConverter<TElement, TOther, TResult>, keyComparer?: Equater<TKey>): Enumerable<TResult> {
return new JoinEnumerable<TElement, TOther, TKey, TResult>(this, Enumerable.wrap(iterable), firstKeySelector, secondKeySelector, resultSelector, keyComparer);
return new JoinEnumerable<TElement, TOther, TKey, TResult>(this, wrap(iterable), firstKeySelector, secondKeySelector, resultSelector, keyComparer);
}
groupJoin<TOther, TKey, TResult>(iterable: Iterable<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector?: BiConverter<TElement, Enumerable<TOther>, TResult>, keyComparer?: Equater<TKey>): Enumerable<TResult> {
return new GroupJoinEnumerable<TElement, TOther, TKey, TResult>(this, Enumerable.wrap(iterable), firstKeySelector, secondKeySelector, resultSelector, keyComparer);
return new GroupJoinEnumerable<TElement, TOther, TKey, TResult>(this, wrap(iterable), firstKeySelector, secondKeySelector, resultSelector, keyComparer);
}
contains(obj: TElement, equater?: Equater<TElement>) {
@@ -343,7 +65,7 @@ export abstract class BaseEnumerable<TElement> extends EnumerableMarker implemen
return true;
}
const that = Enumerable.wrap(iterable);
const that = wrap(iterable);
const thisCount = this.nonEnumeratedCount();
const thatCount = that.nonEnumeratedCount();
@@ -397,7 +119,7 @@ export abstract class BaseEnumerable<TElement> extends EnumerableMarker implemen
const arr: Enumerable<TElement>[] = [this];
for (const iterable of iterables) {
arr.push(Enumerable.wrap(iterable));
arr.push(wrap(iterable));
}
return new ConcatEnumerable(arr);
@@ -741,27 +463,27 @@ export abstract class BaseEnumerable<TElement> extends EnumerableMarker implemen
}
union(iterable: Iterable<TElement>, equater?: Equater<TElement>): Enumerable<TElement> {
return new UnionEnumerable<TElement>(this, Enumerable.wrap(iterable), equater);
return new UnionEnumerable<TElement>(this, wrap(iterable), equater);
}
unionBy<TBy>(iterable: Iterable<TElement>, selector: Converter<TElement, TBy>, equater?: Equater<TBy>): Enumerable<TElement> {
return new UnionByEnumerable<TElement, TBy>(this, Enumerable.wrap(iterable), selector, equater);
return new UnionByEnumerable<TElement, TBy>(this, wrap(iterable), selector, equater);
}
except(iterable: Iterable<TElement>): Enumerable<TElement> {
return new ExceptEnumerable<TElement>(this, Enumerable.wrap(iterable));
return new ExceptEnumerable<TElement>(this, wrap(iterable));
}
exceptBy<TBy>(iterable: Iterable<TElement>, selector: Converter<TElement, TBy>): Enumerable<TElement> {
return new ExceptByEnumerable<TElement, TBy>(this, Enumerable.wrap(iterable), selector);
return new ExceptByEnumerable<TElement, TBy>(this, wrap(iterable), selector);
}
intersect(iterable: Iterable<TElement>): Enumerable<TElement> {
return new IntersectEnumerable<TElement>(this, Enumerable.wrap(iterable));
return new IntersectEnumerable<TElement>(this, wrap(iterable));
}
intersectBy<TBy>(iterable: Iterable<TElement>, selector: Converter<TElement, TBy>): Enumerable<TElement> {
return new IntersectByEnumerable<TElement, TBy>(this, Enumerable.wrap(iterable), selector);
return new IntersectByEnumerable<TElement, TBy>(this, wrap(iterable), selector);
}
all(predicate: Predicate<TElement>) {
@@ -845,7 +567,7 @@ export abstract class BaseEnumerable<TElement> extends EnumerableMarker implemen
throw new Error("Cannot take a negative number of elements.");
}
return n === 0 ? Enumerable.empty<TElement>() : new TakeEnumerable<TElement>(this, n);
return n === 0 ? empty<TElement>() : new TakeEnumerable<TElement>(this, n);
}
takeLast(n: number): Enumerable<TElement> {
@@ -853,7 +575,7 @@ export abstract class BaseEnumerable<TElement> extends EnumerableMarker implemen
throw new Error("Cannot take a negative number of elements.");
}
return n === 0 ? Enumerable.empty<TElement>() : new TakeLastEnumerable<TElement>(this, n);
return n === 0 ? empty<TElement>() : new TakeLastEnumerable<TElement>(this, n);
}
takeWhile(predicate: Predicate<TElement>): Enumerable<TElement> {
@@ -871,7 +593,7 @@ export abstract class BaseEnumerable<TElement> extends EnumerableMarker implemen
}
zip<TOther>(iterable: Iterable<TOther>): Enumerable<[TElement, TOther]> {
return new ZippedEnumerable<TElement, TOther>(this, Enumerable.wrap(iterable));
return new ZippedEnumerable<TElement, TOther>(this, wrap(iterable));
}
indexed(): Enumerable<[number, TElement]> {
@@ -891,7 +613,7 @@ export abstract class BaseEnumerable<TElement> extends EnumerableMarker implemen
}
random(options?: RandomOptions<TElement>) {
return Random.getRandomElement(this, options).element;
return getRandomElement(this, options).element;
}
cached(): Enumerable<TElement> {
@@ -947,7 +669,7 @@ export abstract class BaseEnumerable<TElement> extends EnumerableMarker implemen
}
}
class DelegatedEnumerable<TElement> extends EnumerableMarker implements Enumerable<TElement> {
export class DelegatedEnumerable<TElement> extends EnumerableMarker implements Enumerable<TElement> {
#enumerable: Enumerable<TElement>;
constructor(enumerable: Enumerable<TElement>) {
@@ -1238,7 +960,7 @@ class DelegatedEnumerable<TElement> extends EnumerableMarker implements Enumerab
}
}
class GroupedEnumerableImpl<TKey, TElement> extends DelegatedEnumerable<TElement> implements GroupedEnumerable<TKey, TElement> {
export class GroupedEnumerableImpl<TKey, TElement> extends DelegatedEnumerable<TElement> implements GroupedEnumerable<TKey, TElement> {
readonly #key: TKey;
constructor(key: TKey, grouping: Enumerable<TElement>) {
@@ -1252,7 +974,7 @@ class GroupedEnumerableImpl<TKey, TElement> extends DelegatedEnumerable<TElement
}
}
abstract class BaseOrderedEnumerable<TElement> extends BaseEnumerable<TElement> implements OrderedEnumerable<TElement> {
export abstract class BaseOrderedEnumerable<TElement> extends BaseEnumerable<TElement> implements OrderedEnumerable<TElement> {
readonly #enumerable: Enumerable<TElement>;
readonly #sorter: Comparer<TElement> | undefined;
readonly #descending: boolean;
@@ -1314,7 +1036,7 @@ abstract class BaseOrderedEnumerable<TElement> extends BaseEnumerable<TElement>
}
}
class EmptyEnumerable<T> extends BaseEnumerable<T> {
export class EmptyEnumerable<T> extends BaseEnumerable<T> {
static readonly INSTANCE = new EmptyEnumerable<any>();
override nonEnumeratedCount() {
@@ -1328,7 +1050,7 @@ class EmptyEnumerable<T> extends BaseEnumerable<T> {
override *iterator() { }
}
class RangeEnumerable extends BaseEnumerable<number> {
export class RangeEnumerable extends BaseEnumerable<number> {
readonly #min: number;
readonly #max: number;
readonly #step: number;
@@ -1360,7 +1082,7 @@ class RangeEnumerable extends BaseEnumerable<number> {
}
}
class BigIntRangeEnumerable extends BaseEnumerable<bigint> {
export class BigIntRangeEnumerable extends BaseEnumerable<bigint> {
readonly #min: bigint;
readonly #max: bigint;
readonly #step: bigint;
@@ -1392,7 +1114,7 @@ class BigIntRangeEnumerable extends BaseEnumerable<bigint> {
}
}
class RepeatEnumerable<T> extends BaseEnumerable<T> {
export class RepeatEnumerable<T> extends BaseEnumerable<T> {
readonly #value: T;
readonly #count: number;
@@ -1420,7 +1142,7 @@ class RepeatEnumerable<T> extends BaseEnumerable<T> {
}
}
class RepeatForeverEnumerable<T> extends BaseEnumerable<T> {
export class RepeatForeverEnumerable<T> extends BaseEnumerable<T> {
readonly #value: T;
constructor(value: T) {
@@ -1444,7 +1166,7 @@ class RepeatForeverEnumerable<T> extends BaseEnumerable<T> {
}
}
class WrappedObject<T> extends BaseEnumerable<T> {
export class WrappedObject<T> extends BaseEnumerable<T> {
readonly #obj: T;
constructor(obj: T) {
@@ -1466,7 +1188,7 @@ class WrappedObject<T> extends BaseEnumerable<T> {
}
}
class WrappedIterable<T> extends BaseEnumerable<T> {
export class WrappedIterable<T> extends BaseEnumerable<T> {
readonly #iterable: Iterable<T>;
constructor(iterable: Iterable<T>) {
@@ -1480,7 +1202,7 @@ class WrappedIterable<T> extends BaseEnumerable<T> {
}
}
class WrappedArray<T> extends BaseEnumerable<T> {
export class WrappedArray<T> extends BaseEnumerable<T> {
readonly #array: T[];
constructor(array: T[]) {
@@ -1544,7 +1266,7 @@ class WrappedArray<T> extends BaseEnumerable<T> {
}
}
class WrappedArrayLike<T> extends BaseEnumerable<T> {
export class WrappedArrayLike<T> extends BaseEnumerable<T> {
readonly #arrayLike: ArrayLike<T>;
constructor(arrayLike: ArrayLike<T>) {
@@ -1580,7 +1302,7 @@ class WrappedArrayLike<T> extends BaseEnumerable<T> {
}
}
class WrappedSet<T> extends BaseEnumerable<T> {
export class WrappedSet<T> extends BaseEnumerable<T> {
readonly #set: Set<T>;
constructor(set: Set<T>) {
@@ -1610,7 +1332,7 @@ class WrappedSet<T> extends BaseEnumerable<T> {
}
}
class WrappedMap<K, V> extends BaseEnumerable<[K, V]> {
export class WrappedMap<K, V> extends BaseEnumerable<[K, V]> {
readonly #map: Map<K, V>;
constructor(map: Map<K, V>) {
@@ -1644,7 +1366,7 @@ class WrappedMap<K, V> extends BaseEnumerable<[K, V]> {
}
}
class GeneratorEnumerable<T> extends BaseEnumerable<T> {
export class GeneratorEnumerable<T> extends BaseEnumerable<T> {
readonly #generator: () => Iterable<T>;
constructor(generator: () => Iterable<T>) {
@@ -1658,7 +1380,7 @@ class GeneratorEnumerable<T> extends BaseEnumerable<T> {
}
}
class FunctionEnumerable<T> extends BaseEnumerable<T> {
export class FunctionEnumerable<T> extends BaseEnumerable<T> {
readonly #f: () => T;
constructor(f: () => T) {
@@ -1682,7 +1404,7 @@ class FunctionEnumerable<T> extends BaseEnumerable<T> {
}
}
class ConcatEnumerable<T> extends BaseEnumerable<T> {
export class ConcatEnumerable<T> extends BaseEnumerable<T> {
readonly #enumerables: Iterable<Enumerable<T>>;
constructor(enumerables: Iterable<Enumerable<T>>) {
@@ -1734,7 +1456,7 @@ class ConcatEnumerable<T> extends BaseEnumerable<T> {
}
}
class DistinctEnumerable<T> extends BaseEnumerable<T> {
export class DistinctEnumerable<T> extends BaseEnumerable<T> {
readonly #enumerable: Enumerable<T>;
readonly #equater: Equater<T> | undefined;
@@ -1760,7 +1482,7 @@ class DistinctEnumerable<T> extends BaseEnumerable<T> {
}
}
class DistinctByEnumerable<T, U> extends BaseEnumerable<T> {
export class DistinctByEnumerable<T, U> extends BaseEnumerable<T> {
readonly #enumerable: Enumerable<T>;
readonly #selector: Converter<T, U>;
readonly #equater: Equater<U> | undefined;
@@ -1788,7 +1510,7 @@ class DistinctByEnumerable<T, U> extends BaseEnumerable<T> {
}
}
class WhereEnumerable<TElement, TFiltered extends TElement> extends BaseEnumerable<TFiltered> {
export class WhereEnumerable<TElement, TFiltered extends TElement> extends BaseEnumerable<TFiltered> {
readonly #enumerable: Enumerable<TElement>;
readonly #predicate: FilterPredicate<TElement, TFiltered>;
@@ -1812,7 +1534,7 @@ class WhereEnumerable<TElement, TFiltered extends TElement> extends BaseEnumerab
}
}
class SelectManyEnumerable<T, U> extends BaseEnumerable<U> {
export class SelectManyEnumerable<T, U> extends BaseEnumerable<U> {
readonly #enumerable: Enumerable<T>;
readonly #converter: Converter<T, Iterable<U>>;
@@ -1830,7 +1552,7 @@ class SelectManyEnumerable<T, U> extends BaseEnumerable<U> {
}
}
class IndexedEnumerable<T> extends BaseEnumerable<[number, T]> {
export class IndexedEnumerable<T> extends BaseEnumerable<[number, T]> {
readonly #enumerable: Enumerable<T>;
constructor(enumerable: Enumerable<T>) {
@@ -1856,7 +1578,7 @@ class IndexedEnumerable<T> extends BaseEnumerable<[number, T]> {
}
}
class SelectEnumerable<T, U> extends BaseEnumerable<U> {
export class SelectEnumerable<T, U> extends BaseEnumerable<U> {
readonly #enumerable: Enumerable<T>;
readonly #converter: Converter<T, U>;
@@ -1882,7 +1604,7 @@ class SelectEnumerable<T, U> extends BaseEnumerable<U> {
}
}
class SkipWhileEnumerable<T> extends BaseEnumerable<T> {
export class SkipWhileEnumerable<T> extends BaseEnumerable<T> {
readonly #enumerable: Enumerable<T>;
readonly #predicate: Predicate<T>;
@@ -1911,7 +1633,7 @@ class SkipWhileEnumerable<T> extends BaseEnumerable<T> {
}
}
class SkipLastEnumerable<T> extends BaseEnumerable<T> {
export class SkipLastEnumerable<T> extends BaseEnumerable<T> {
readonly #enumerable: Enumerable<T>;
readonly #n: number;
@@ -1956,7 +1678,7 @@ class SkipLastEnumerable<T> extends BaseEnumerable<T> {
}
}
class SkipEnumerable<T> extends BaseEnumerable<T> {
export class SkipEnumerable<T> extends BaseEnumerable<T> {
readonly #enumerable: Enumerable<T>;
readonly #n: number;
@@ -1992,7 +1714,7 @@ class SkipEnumerable<T> extends BaseEnumerable<T> {
}
}
class TakeWhileEnumerable<T> extends BaseEnumerable<T> {
export class TakeWhileEnumerable<T> extends BaseEnumerable<T> {
readonly #enumerable: Enumerable<T>;
readonly #predicate: Predicate<T>;
@@ -2018,7 +1740,7 @@ class TakeWhileEnumerable<T> extends BaseEnumerable<T> {
}
}
class TakeLastEnumerable<T> extends BaseEnumerable<T> {
export class TakeLastEnumerable<T> extends BaseEnumerable<T> {
readonly #enumerable: Enumerable<T>;
readonly #n: number;
@@ -2049,7 +1771,7 @@ class TakeLastEnumerable<T> extends BaseEnumerable<T> {
}
}
class TakeEnumerable<T> extends BaseEnumerable<T> {
export class TakeEnumerable<T> extends BaseEnumerable<T> {
readonly #enumerable: Enumerable<T>;
readonly #n: number;
@@ -2086,13 +1808,13 @@ class TakeEnumerable<T> extends BaseEnumerable<T> {
}
}
class OrderEnumerable<T> extends BaseOrderedEnumerable<T> {
export class OrderEnumerable<T> extends BaseOrderedEnumerable<T> {
constructor(enumerable: Enumerable<T>, descending: boolean, sorter?: Comparer<T>) {
super(enumerable, sorter, descending);
}
}
class OrderByEnumerable<T, U> extends BaseOrderedEnumerable<T> {
export class OrderByEnumerable<T, U> extends BaseOrderedEnumerable<T> {
constructor(enumerable: Enumerable<T>, descending: boolean, selector: Converter<T, U>, sorter?: Comparer<U>) {
super(enumerable, OrderByEnumerable.#createSorter(selector, sorter), descending);
}
@@ -2103,13 +1825,13 @@ class OrderByEnumerable<T, U> extends BaseOrderedEnumerable<T> {
}
}
class ThenOrderEnumerable<T> extends BaseOrderedEnumerable<T> {
export class ThenOrderEnumerable<T> extends BaseOrderedEnumerable<T> {
constructor(enumerable: OrderedEnumerable<T>, descending: boolean, sorter?: Comparer<T>) {
super(enumerable, combineComparers(enumerable.comparer ?? defaultArrayComparer, sorter ?? defaultArrayComparer), descending);
}
}
class ThenOrderByEnumerable<T, U> extends BaseOrderedEnumerable<T> {
export class ThenOrderByEnumerable<T, U> extends BaseOrderedEnumerable<T> {
constructor(enumerable: OrderedEnumerable<T>, descending: boolean, selector: Converter<T, U>, sorter?: Comparer<U>) {
super(enumerable, ThenOrderByEnumerable.#createCombinedSorter(enumerable.comparer, selector, sorter), descending);
}
@@ -2121,7 +1843,7 @@ class ThenOrderByEnumerable<T, U> extends BaseOrderedEnumerable<T> {
}
}
class AppendEnumerable<T> extends BaseEnumerable<T> {
export class AppendEnumerable<T> extends BaseEnumerable<T> {
readonly #enumerable: Enumerable<T>;
readonly #obj: T;
@@ -2147,7 +1869,7 @@ class AppendEnumerable<T> extends BaseEnumerable<T> {
}
}
class PrependEnumerable<T> extends BaseEnumerable<T> {
export class PrependEnumerable<T> extends BaseEnumerable<T> {
readonly #enumerable: Enumerable<T>;
readonly #obj: T;
@@ -2173,7 +1895,7 @@ class PrependEnumerable<T> extends BaseEnumerable<T> {
}
}
class PeekEnumerable<T> extends DelegatedEnumerable<T> {
export class PeekEnumerable<T> extends DelegatedEnumerable<T> {
readonly #action: Action<T>;
constructor(enumerable: Enumerable<T>, action: Action<T>) {
@@ -2190,7 +1912,7 @@ class PeekEnumerable<T> extends DelegatedEnumerable<T> {
}
}
class ZippedEnumerable<T, U> extends BaseEnumerable<[T, U]> {
export class ZippedEnumerable<T, U> extends BaseEnumerable<[T, U]> {
readonly #first: Enumerable<T>;
readonly #second: Enumerable<U>;
@@ -2229,7 +1951,7 @@ class ZippedEnumerable<T, U> extends BaseEnumerable<[T, U]> {
}
}
class UnionEnumerable<T> extends BaseEnumerable<T> {
export class UnionEnumerable<T> extends BaseEnumerable<T> {
readonly #first: Enumerable<T>;
readonly #second: Enumerable<T>;
readonly #equater: Equater<T> | undefined;
@@ -2262,7 +1984,7 @@ class UnionEnumerable<T> extends BaseEnumerable<T> {
}
}
class UnionByEnumerable<T, U> extends BaseEnumerable<T> {
export class UnionByEnumerable<T, U> extends BaseEnumerable<T> {
readonly #first: Enumerable<T>;
readonly #second: Enumerable<T>;
readonly #selector: Converter<T, U>;
@@ -2297,7 +2019,7 @@ class UnionByEnumerable<T, U> extends BaseEnumerable<T> {
}
}
class ExceptEnumerable<T> extends BaseEnumerable<T> {
export class ExceptEnumerable<T> extends BaseEnumerable<T> {
readonly #first: Enumerable<T>;
readonly #second: Enumerable<T>;
readonly #equater: Equater<T> | undefined;
@@ -2329,7 +2051,7 @@ class ExceptEnumerable<T> extends BaseEnumerable<T> {
}
}
class ExceptByEnumerable<T, U> extends BaseEnumerable<T> {
export class ExceptByEnumerable<T, U> extends BaseEnumerable<T> {
readonly #first: Enumerable<T>;
readonly #second: Enumerable<T>;
readonly #selector: Converter<T, U>;
@@ -2363,7 +2085,7 @@ class ExceptByEnumerable<T, U> extends BaseEnumerable<T> {
}
}
class IntersectEnumerable<T> extends BaseEnumerable<T> {
export class IntersectEnumerable<T> extends BaseEnumerable<T> {
readonly #first: Enumerable<T>;
readonly #second: Enumerable<T>;
readonly #equater: Equater<T> | undefined;
@@ -2395,7 +2117,7 @@ class IntersectEnumerable<T> extends BaseEnumerable<T> {
}
}
class IntersectByEnumerable<T, U> extends BaseEnumerable<T> {
export class IntersectByEnumerable<T, U> extends BaseEnumerable<T> {
readonly #first: Enumerable<T>;
readonly #second: Enumerable<T>;
readonly #selector: Converter<T, U>;
@@ -2429,7 +2151,7 @@ class IntersectByEnumerable<T, U> extends BaseEnumerable<T> {
}
}
class ReversedEnumerable<T> extends BaseEnumerable<T> {
export class ReversedEnumerable<T> extends BaseEnumerable<T> {
readonly #enumerable: Enumerable<T>;
constructor(enumerable: Enumerable<T>) {
@@ -2459,7 +2181,7 @@ class ReversedEnumerable<T> extends BaseEnumerable<T> {
}
}
class GroupByEnumerable<TElement, TKey, TResult> extends BaseEnumerable<GroupedEnumerable<TKey, TResult>> {
export class GroupByEnumerable<TElement, TKey, TResult> extends BaseEnumerable<GroupedEnumerable<TKey, TResult>> {
readonly #enumerable: Enumerable<TElement>;
readonly #keySelector: Converter<TElement, TKey>;
readonly #elementSelector: Converter<TElement, TResult>;
@@ -2493,12 +2215,12 @@ class GroupByEnumerable<TElement, TKey, TResult> extends BaseEnumerable<GroupedE
}
for (const entry of groupings) {
yield new GroupedEnumerableImpl(entry[0], Enumerable.array(entry[1]));
yield new GroupedEnumerableImpl(entry[0], array(entry[1]));
}
}
}
class ChunkedEnumerable<T> extends BaseEnumerable<T[]> {
export class ChunkedEnumerable<T> extends BaseEnumerable<T[]> {
readonly #enumerable: Enumerable<T>;
readonly #size: number;
@@ -2536,7 +2258,7 @@ class ChunkedEnumerable<T> extends BaseEnumerable<T[]> {
}
}
class JoinEnumerable<TOuter, TInner, TKey, TResult> extends BaseEnumerable<TResult> {
export class JoinEnumerable<TOuter, TInner, TKey, TResult> extends BaseEnumerable<TResult> {
readonly #first: Enumerable<TOuter>;
readonly #second: Enumerable<TInner>;
readonly #firstKeySelector: Converter<TOuter, TKey>;
@@ -2578,7 +2300,7 @@ class JoinEnumerable<TOuter, TInner, TKey, TResult> extends BaseEnumerable<TResu
}
}
class GroupJoinEnumerable<TOuter, TInner, TKey, TResult> extends BaseEnumerable<TResult> {
export class GroupJoinEnumerable<TOuter, TInner, TKey, TResult> extends BaseEnumerable<TResult> {
readonly #first: Enumerable<TOuter>;
readonly #second: Enumerable<TInner>;
readonly #firstKeySelector: Converter<TOuter, TKey>;
@@ -2622,12 +2344,12 @@ class GroupJoinEnumerable<TOuter, TInner, TKey, TResult> extends BaseEnumerable<
}
}
yield this.#resultSelector(firstObj, Enumerable.array(secondObjs));
yield this.#resultSelector(firstObj, array(secondObjs));
}
}
}
class RemoveEnumerable<T> extends BaseEnumerable<T> {
export class RemoveEnumerable<T> extends BaseEnumerable<T> {
readonly #enumerable: Enumerable<T>;
readonly #obj: T;
readonly #all: boolean;
@@ -2666,7 +2388,7 @@ class RemoveEnumerable<T> extends BaseEnumerable<T> {
}
}
class CacheEnumerable<T> extends DelegatedEnumerable<T> {
export class CacheEnumerable<T> extends DelegatedEnumerable<T> {
#cached = false;
constructor(enumerable: Enumerable<T>) {
@@ -2675,12 +2397,10 @@ class CacheEnumerable<T> extends DelegatedEnumerable<T> {
override iterator() {
if (!this.#cached) {
this.enumerable = Enumerable.array(this.enumerable.toArray());
this.enumerable = array(this.enumerable.toArray());
this.#cached = true;
}
return super.iterator();
}
}
//#endregion

147
src/sync/index.ts Normal file
View File

@@ -0,0 +1,147 @@
import { mathRandom } from "../random/index.js";
import { RandomGenerator } from "../random/types.js";
import { BigIntRangeEnumerable, ConcatEnumerable, EmptyEnumerable, EnumerableMarker, FunctionEnumerable, GeneratorEnumerable, RangeEnumerable, RepeatEnumerable, RepeatForeverEnumerable, WrappedArray, WrappedArrayLike, WrappedIterable, WrappedMap, WrappedObject, WrappedSet } from "./impl.js";
import { Enumerable } from "./types.js";
export function wrap<T>(iterable: Iterable<T>): Enumerable<T> {
if (isEnumerable<T>(iterable)) {
return iterable;
}
if (Array.isArray(iterable)) {
return array(iterable);
}
if (iterable instanceof Set) {
return set<T>(iterable);
}
if (iterable instanceof Map) {
return map(iterable) as unknown as Enumerable<T>;
}
return sequence(iterable);
}
export function sequence<T>(iterable: Iterable<T>): Enumerable<T> {
return new WrappedIterable(iterable);
}
export function empty<T>(): Enumerable<T> {
return EmptyEnumerable.INSTANCE;
}
export function single<T>(obj: T): Enumerable<T> {
return new WrappedObject(obj);
}
export function array<T>(array: T[]): Enumerable<T> {
return new WrappedArray(array);
}
export function arrayLike<T>(arrayLike: ArrayLike<T>): Enumerable<T> {
return new WrappedArrayLike(arrayLike);
}
export function set<T>(set: Set<T>): Enumerable<T> {
return new WrappedSet(set);
}
export function map<K, V>(map: Map<K, V>): Enumerable<[K, V]> {
return new WrappedMap(map);
}
export function of<T>(...elements: T[]): Enumerable<T> {
switch (elements.length) {
case 0:
return empty();
case 1:
return single(elements[0]);
default:
return array(elements);
}
}
export function ofPropertyKeys<T extends PropertyKey>(...elements: T[]): Enumerable<T> {
return of(...elements);
}
export function entries<T>(o: Record<string, T> | ArrayLike<T>): Enumerable<[string, T]> {
return array(Object.entries(o));
}
export function keys(o: object): Enumerable<string> {
return array(Object.keys(o));
}
export function func<T>(f: () => T): Enumerable<T> {
return new FunctionEnumerable(f);
}
export function generator<T>(generator: () => Iterable<T>): Enumerable<T> {
return new GeneratorEnumerable(generator);
}
export function range(max: number): Enumerable<number>
export function range(min: number, max: number): Enumerable<number>
export function range(min: number, max: number, step: number): Enumerable<number>
export function range(a: number, b?: number, c?: number): Enumerable<number> {
if (b === undefined) {
b = a;
a = 0;
}
if (c === undefined) {
c = 1;
}
return new RangeEnumerable(a, b, c);
}
export function bigintRange(max: bigint): Enumerable<bigint>
export function bigintRange(min: bigint, max: bigint): Enumerable<bigint>
export function bigintRange(min: bigint, max: bigint, step: bigint): Enumerable<bigint>
export function bigintRange(a: bigint, b?: bigint, c?: bigint): Enumerable<bigint> {
if (b === undefined) {
b = a;
a = 0n;
}
if (c === undefined) {
c = 1n;
}
return new BigIntRangeEnumerable(a, b, c);
}
export function repeat<T>(value: T, count?: number): Enumerable<T> {
if (count == undefined) {
return new RepeatForeverEnumerable(value);
}
if (count < 0) {
throw new RangeError();
}
if (count === 0) {
return empty();
}
if (count === 1) {
return new WrappedObject(value);
}
return new RepeatEnumerable(value, count);
}
export function randomSequence(random?: RandomGenerator): Enumerable<number> {
return new FunctionEnumerable(random ?? mathRandom);
}
export function concat<T>(...enumerables: Enumerable<T>[]): Enumerable<T> {
return new ConcatEnumerable(enumerables);
}
export function isEnumerable<T = any>(obj: any): obj is Enumerable<T> {
return obj instanceof EnumerableMarker;
}

135
src/sync/types.ts Normal file
View File

@@ -0,0 +1,135 @@
import { Collector } from "../collector/types.js";
import { RandomOptions } from "../random/types.js";
import { Predicate, Converter, FilterPredicate, Equater, BiConverter, Accumulator, Comparer, Action } from "../types.js";
export interface Enumerable<TElement> extends Iterable<TElement> {
iterator(): Iterator<TElement>;
apply<TResult>(pipeline: (enumerable: Enumerable<TElement>) => TResult): TResult;
count(predicate?: Predicate<TElement>): number;
nonEnumeratedCount(): number;
fastCount(): number;
maxCount(): number;
select<TResult>(selector: Converter<TElement, TResult>): Enumerable<TResult>;
selectMany<TResult>(selector: Converter<TElement, Iterable<TResult>>): Enumerable<TResult>;
where<TFiltered extends TElement>(predicate: FilterPredicate<TElement, TFiltered>): Enumerable<TFiltered>;
where(predicate: Predicate<TElement>): Enumerable<TElement>;
groupBy<TKey>(keySelector: Converter<TElement, TKey>, elementSelector?: undefined, keyComparer?: Equater<TKey>): Enumerable<GroupedEnumerable<TKey, TElement>>;
groupBy<TKey, TResult>(keySelector: Converter<TElement, TKey>, elementSelector: Converter<TElement, TResult>, keyComparer?: Equater<TKey>): Enumerable<GroupedEnumerable<TKey, TResult>>;
join<TOther, TKey>(iterable: Iterable<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector?: undefined, keyComparer?: Equater<TKey>): Enumerable<[TElement, TOther]>;
join<TOther, TKey, TResult>(iterable: Iterable<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector: BiConverter<TElement, TOther, TResult>, keyComparer?: Equater<TKey>): Enumerable<TResult>;
groupJoin<TOther, TKey>(iterable: Iterable<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector?: undefined, keyComparer?: Equater<TKey>): Enumerable<GroupedEnumerable<TElement, TOther>>;
groupJoin<TOther, TKey, TResult>(iterable: Iterable<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector: BiConverter<TElement, Enumerable<TOther>, TResult>, keyComparer?: Equater<TKey>): Enumerable<TResult>;
contains(obj: TElement, equater?: Equater<TElement>): boolean;
sequenceEquals(iterable: Iterable<TElement>, equater?: Equater<TElement>): boolean;
append(obj: TElement): Enumerable<TElement>;
prepend(obj: TElement): Enumerable<TElement>;
remove(obj: TElement, all?: boolean, equater?: Equater<TElement>): Enumerable<TElement>;
concat(...iterables: Iterable<TElement>[]): Enumerable<TElement>;
first(predicate?: Predicate<TElement>): TElement;
firstOrDefault(predicate?: Predicate<TElement>, def?: TElement): TElement | undefined;
last(predicate?: Predicate<TElement>): TElement;
lastOrDefault(predicate?: Predicate<TElement>, def?: TElement): TElement | undefined;
single(predicate?: Predicate<TElement>): TElement;
singleOrDefault(predicate?: Predicate<TElement>, def?: TElement): TElement | undefined;
elementAt(index: number): TElement;
elementAtOrDefault(index: number, def?: TElement): TElement | undefined;
aggregate(accumulator: Accumulator<TElement, TElement>): TElement;
aggregate<TAccumulator>(accumulator: Accumulator<TElement, TAccumulator>, seed?: TAccumulator): TAccumulator;
aggregate<TAccumulator, TResult>(accumulator: Accumulator<TElement, TAccumulator>, seed?: TAccumulator, resultSelector?: Converter<TAccumulator, TResult>): TResult;
min(comparer?: Comparer<TElement>): TElement;
minBy<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): TElement;
max(comparer?: Comparer<TElement>): TElement;
maxBy<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): TElement;
order(comparer?: Comparer<TElement>): OrderedEnumerable<TElement>;
orderBy<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): OrderedEnumerable<TElement>;
orderDescending(comparer?: Comparer<TElement>): OrderedEnumerable<TElement>;
orderByDescending<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): OrderedEnumerable<TElement>;
distinct(equater?: Equater<TElement>): Enumerable<TElement>;
distinctBy<TBy>(selector: Converter<TElement, TBy>, equater?: Equater<TBy>): Enumerable<TElement>;
union(iterable: Iterable<TElement>, equater?: Equater<TElement>): Enumerable<TElement>;
unionBy<TBy>(iterable: Iterable<TElement>, selector: Converter<TElement, TBy>, equater?: Equater<TBy>): Enumerable<TElement>;
except(iterable: Iterable<TElement>, equater?: Equater<TElement>): Enumerable<TElement>;
exceptBy<TBy>(iterable: Iterable<TElement>, selector: Converter<TElement, TBy>, equater?: Equater<TBy>): Enumerable<TElement>;
intersect(iterable: Iterable<TElement>, equater?: Equater<TElement>): Enumerable<TElement>;
intersectBy<TBy>(iterable: Iterable<TElement>, selector: Converter<TElement, TBy>, equater?: Equater<TBy>): Enumerable<TElement>;
all(predicate: Predicate<TElement>): boolean;
any(predicate: Predicate<TElement>): boolean;
any(): boolean;
none(predicate: Predicate<TElement>): boolean;
none(): boolean;
skip(n: number): Enumerable<TElement>;
skipLast(n: number): Enumerable<TElement>;
skipWhile(condition: Predicate<TElement>): Enumerable<TElement>;
take(n: number): Enumerable<TElement>;
takeLast(n: number): Enumerable<TElement>;
takeWhile(condition: Predicate<TElement>): Enumerable<TElement>;
peek(action: Action<TElement>): Enumerable<TElement>;
forEach(action: Action<TElement>): void;
zip<TOther>(iterable: Iterable<TOther>): Enumerable<[TElement, TOther]>;
indexed(): Enumerable<[number, TElement]>;
reversed(): Enumerable<TElement>;
chunked(size: number): Enumerable<TElement[]>;
random(options?: RandomOptions<TElement>): TElement | undefined;
cached(): Enumerable<TElement>;
asArray(): TElement[];
toArray(): TElement[];
toMap<TKey, TValue>(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>): Map<TKey, TValue>;
toSet(): Set<TElement>;
toObject<TKey extends PropertyKey, TValue>(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>): Record<TKey, TValue>;
collect<TResult>(collector: Collector<TElement, any, TResult>): TResult;
}
export interface GroupedEnumerable<TKey, TElement> extends Enumerable<TElement> {
get key(): TKey;
}
export interface OrderedEnumerable<TElement> extends Enumerable<TElement> {
get comparer(): Comparer<TElement> | undefined;
thenSelf(comparer?: Comparer<TElement>): OrderedEnumerable<TElement>;
thenBy<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): OrderedEnumerable<TElement>;
thenSelfDescending(comparer?: Comparer<TElement>): OrderedEnumerable<TElement>;
thenByDescending<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): OrderedEnumerable<TElement>;
}