change project structure to remove namespaces
This commit is contained in:
@@ -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
101
src/async/index.ts
Normal 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
133
src/async/types.ts
Normal 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>;
|
||||
}
|
||||
@@ -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
29
src/bitarray/index.ts
Normal 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
26
src/bitarray/types.ts
Normal 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;
|
||||
}
|
||||
247
src/collector.ts
247
src/collector.ts
@@ -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
187
src/collector/impl.ts
Normal 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
56
src/collector/index.ts
Normal 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
5
src/collector/types.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export interface Collector<TElement, TAccumulator, TResult> {
|
||||
initialize(): TAccumulator;
|
||||
accumulate(accumulator: TAccumulator, element: TElement): void;
|
||||
finalize(accumulator: TAccumulator): TResult;
|
||||
}
|
||||
16
src/index.ts
16
src/index.ts
@@ -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";
|
||||
|
||||
136
src/random.ts
136
src/random.ts
@@ -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
162
src/random/index.ts
Normal 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
20
src/random/types.ts
Normal 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;
|
||||
};
|
||||
@@ -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
147
src/sync/index.ts
Normal 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
135
src/sync/types.ts
Normal 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>;
|
||||
}
|
||||
Reference in New Issue
Block a user