2144 lines
60 KiB
TypeScript
2144 lines
60 KiB
TypeScript
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 { Sequence } 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 { AsyncSequence, GroupedAsyncSequence, OrderedAsyncSequence } from "./types.js";
|
|
|
|
export class AsyncSequenceMarker { }
|
|
|
|
export abstract class BaseAsyncSequence<TElement> extends AsyncSequenceMarker implements AsyncSequence<TElement> {
|
|
[Symbol.asyncIterator]() {
|
|
return this.iterator();
|
|
}
|
|
|
|
abstract iterator(): AsyncIterator<Awaited<TElement>>;
|
|
|
|
apply<TResult>(pipeline: (sequence: AsyncSequence<TElement>) => TResult): TResult {
|
|
return pipeline(this);
|
|
}
|
|
|
|
select<TResult>(converter: MaybeAsyncConverter<TElement, TResult>): AsyncSequence<TResult> {
|
|
return new MapperAsyncSequence<TElement, TResult>(this, converter);
|
|
}
|
|
|
|
selectMany<TResult>(converter: MaybeAsyncConverter<TElement, MaybeAsyncIterable<TResult>>): AsyncSequence<TResult> {
|
|
return new FlatMapperAsyncSequence<TElement, TResult>(this, converter);
|
|
}
|
|
|
|
where(predicate: MaybeAsyncPredicate<TElement>): AsyncSequence<TElement> {
|
|
return new FilterAsyncSequence<TElement>(this, predicate);
|
|
}
|
|
|
|
groupBy<TKey, TResult>(keySelector: MaybeAsyncConverter<TElement, TKey>, elementSelector?: MaybeAsyncConverter<TElement, TResult>, keyComparer?: MaybeAsyncEquater<TKey>): AsyncSequence<GroupedAsyncSequence<TKey, TResult>> {
|
|
return new GroupByAsyncSequence<TElement, TKey, TResult>(this, keySelector, elementSelector, keyComparer);
|
|
}
|
|
|
|
join<TOther, TKey, TResult>(iterable: MaybeAsyncIterable<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector?: MaybeAsyncBiConverter<TElement, TOther, TResult>, keyComparer?: MaybeAsyncEquater<TKey>): AsyncSequence<TResult> {
|
|
return new JoinAsyncSequence<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, AsyncSequence<TOther>, TResult>, keyComparer?: MaybeAsyncEquater<TKey>): AsyncSequence<TResult> {
|
|
return new GroupJoinAsyncSequence<TElement, TOther, TKey, TResult>(this, wrap(iterable), firstKeySelector, secondKeySelector, resultSelector, keyComparer);
|
|
}
|
|
|
|
async contains(obj: TElement, equater?: MaybeAsyncEquater<TElement>) {
|
|
if (!equater) {
|
|
equater = strictEquals;
|
|
}
|
|
|
|
for await (const element of this) {
|
|
if (await equater(element, obj)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
async sequenceEquals(iterable: MaybeAsyncIterable<TElement>, equater?: MaybeAsyncEquater<TElement>) {
|
|
if (this === iterable) {
|
|
return true;
|
|
}
|
|
|
|
const that = wrap(iterable);
|
|
|
|
const thisCount = await this.nonEnumeratedCount();
|
|
const thatCount = await that.nonEnumeratedCount();
|
|
|
|
if (thisCount >= 0 && thatCount >= 0 && thisCount !== thatCount) {
|
|
return false;
|
|
}
|
|
|
|
if (!equater) {
|
|
equater = strictEquals;
|
|
}
|
|
|
|
const thisIterator = this.iterator();
|
|
const thatIterator = that.iterator();
|
|
|
|
while (true) {
|
|
const thisNext = await thisIterator.next();
|
|
const thatNext = await thatIterator.next();
|
|
|
|
if (thisNext.done) {
|
|
return thatNext.done === true;
|
|
}
|
|
|
|
if (thatNext.done) {
|
|
return false;
|
|
}
|
|
|
|
if (!await equater(thisNext.value, thatNext.value)) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
append(obj: TElement): AsyncSequence<TElement> {
|
|
return new AppendAsyncSequence<TElement>(this, obj);
|
|
}
|
|
|
|
prepend(obj: TElement): AsyncSequence<TElement> {
|
|
return new PrependAsyncSequence<TElement>(this, obj);
|
|
}
|
|
|
|
remove(obj: TElement, all?: boolean, equater?: MaybeAsyncEquater<TElement>): AsyncSequence<TElement> {
|
|
return new RemoveAsyncSequence<TElement>(this, obj, all, equater);
|
|
}
|
|
|
|
concat(...iterables: MaybeAsyncIterable<TElement>[]): AsyncSequence<TElement> {
|
|
if (iterables.length === 0) {
|
|
return this;
|
|
}
|
|
|
|
const arr: AsyncSequence<TElement>[] = [this];
|
|
|
|
for (const iterable of iterables) {
|
|
arr.push(wrap(iterable));
|
|
}
|
|
|
|
return new ConcatAsyncSequence(arr);
|
|
}
|
|
|
|
async count(predicate?: MaybeAsyncPredicate<TElement>) {
|
|
let count = 0;
|
|
|
|
if (predicate) {
|
|
for await (const element of this) {
|
|
if (await predicate(element)) {
|
|
count++;
|
|
}
|
|
}
|
|
} else {
|
|
const iterator = this.iterator();
|
|
|
|
while (!(await iterator.next()).done) {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
async nonEnumeratedCount() {
|
|
return -1;
|
|
}
|
|
|
|
async fastCount() {
|
|
const n = await this.nonEnumeratedCount();
|
|
return n >= 0 ? n : await this.count();
|
|
}
|
|
|
|
async maxCount() {
|
|
const n = await this.nonEnumeratedCount();
|
|
return n >= 0 ? n : Infinity;
|
|
}
|
|
|
|
async #tryGetFirst(predicate?: MaybeAsyncPredicate<TElement>) {
|
|
if (predicate) {
|
|
for await (const element of this) {
|
|
if (await predicate(element)) {
|
|
return {
|
|
found: true,
|
|
element
|
|
} as const;
|
|
}
|
|
}
|
|
} else {
|
|
const next = await this.iterator().next();
|
|
|
|
if (!next.done) {
|
|
return {
|
|
found: true,
|
|
element: next.value
|
|
} as const;
|
|
}
|
|
}
|
|
|
|
return {
|
|
found: false
|
|
} as const;
|
|
}
|
|
|
|
async first(predicate?: MaybeAsyncPredicate<TElement>) {
|
|
const result = await this.#tryGetFirst(predicate);
|
|
|
|
if (result.found) {
|
|
return result.element;
|
|
}
|
|
|
|
throw new Error("No element was found.");
|
|
}
|
|
|
|
async firstOrDefault(predicate?: MaybeAsyncPredicate<TElement>, def?: TElement) {
|
|
const result = await this.#tryGetFirst(predicate);
|
|
|
|
return result.found ? result.element : def;
|
|
}
|
|
|
|
async #tryGetLast(predicate?: MaybeAsyncPredicate<TElement>) {
|
|
let found = false;
|
|
let result: TElement | undefined = undefined;
|
|
|
|
if (predicate) {
|
|
for await (const element of this) {
|
|
if (await predicate(element)) {
|
|
found = true;
|
|
result = element;
|
|
}
|
|
}
|
|
} else {
|
|
for await (const element of this) {
|
|
found = true;
|
|
result = element;
|
|
}
|
|
}
|
|
|
|
return {
|
|
found,
|
|
element: result
|
|
};
|
|
}
|
|
|
|
async last(predicate?: MaybeAsyncPredicate<TElement>) {
|
|
const result = await this.#tryGetLast(predicate);
|
|
|
|
if (result.found) {
|
|
return result.element!;
|
|
}
|
|
|
|
throw new Error("No element was found.");
|
|
}
|
|
|
|
async lastOrDefault(predicate?: MaybeAsyncPredicate<TElement>, def?: TElement) {
|
|
const result = await this.#tryGetLast(predicate);
|
|
|
|
return result.found ? result.element : def;
|
|
}
|
|
|
|
async #tryGetSingle(predicate?: MaybeAsyncPredicate<TElement>) {
|
|
if (predicate) {
|
|
let result: { found: true; element: TElement; } | undefined = undefined;
|
|
|
|
for await (const element of this) {
|
|
if (await predicate(element)) {
|
|
if (result) {
|
|
return {
|
|
found: false,
|
|
reason: 2
|
|
} as const;
|
|
}
|
|
|
|
result = {
|
|
found: true,
|
|
element
|
|
} as const;
|
|
}
|
|
}
|
|
} else {
|
|
const iterator = this.iterator();
|
|
let next = await iterator.next();
|
|
|
|
if (!next.done) {
|
|
const result = {
|
|
found: true,
|
|
element: next.value
|
|
} as const;
|
|
|
|
next = await iterator.next();
|
|
|
|
if (next.done) {
|
|
return result;
|
|
}
|
|
|
|
return {
|
|
found: false,
|
|
reason: 2
|
|
} as const;
|
|
}
|
|
}
|
|
|
|
return {
|
|
found: false,
|
|
reason: 1
|
|
} as const;
|
|
}
|
|
|
|
async single(predicate?: MaybeAsyncPredicate<TElement>) {
|
|
const result = await this.#tryGetSingle(predicate);
|
|
|
|
if (result.found == true) {
|
|
return result.element;
|
|
}
|
|
|
|
let reason: string;
|
|
switch (result.reason) {
|
|
case 1:
|
|
reason = "No element was found.";
|
|
break;
|
|
case 2:
|
|
reason = "More than one element was found.";
|
|
break;
|
|
default:
|
|
reason = "";
|
|
}
|
|
throw new Error(reason);
|
|
}
|
|
|
|
async singleOrDefault(predicate?: MaybeAsyncPredicate<TElement>, def?: TElement) {
|
|
const result = await this.#tryGetSingle(predicate);
|
|
|
|
return result.found ? result.element : def;
|
|
}
|
|
|
|
async #tryElementAt(index: number) {
|
|
let i = index;
|
|
|
|
for await (const element of this) {
|
|
if (i === 0) {
|
|
return {
|
|
found: true,
|
|
element
|
|
} as const;
|
|
}
|
|
|
|
i--;
|
|
}
|
|
|
|
return {
|
|
found: false
|
|
} as const;
|
|
}
|
|
|
|
async elementAt(index: number) {
|
|
const result = await this.#tryElementAt(index);
|
|
|
|
if (result.found) {
|
|
return result.element;
|
|
}
|
|
|
|
throw new Error("No element found at given index.");
|
|
}
|
|
|
|
async elementAtOrDefault(index: number, def?: TElement) {
|
|
const result = await this.#tryElementAt(index);
|
|
|
|
return result.found ? result.element : def;
|
|
}
|
|
|
|
async aggregate<TAccumulator, TResult>(accumulator: MaybeAsyncAccumulator<TElement, TAccumulator>, seed?: TAccumulator, resultSelector?: MaybeAsyncConverter<TAccumulator, TResult>) {
|
|
const iterator = this.iterator();
|
|
|
|
if (seed === undefined) {
|
|
const next = await iterator.next();
|
|
|
|
if (next.done) {
|
|
throw new Error("Aggregation requires at least one element.");
|
|
}
|
|
|
|
seed = next.value as unknown as TAccumulator;
|
|
}
|
|
|
|
let acc = seed;
|
|
|
|
while (true) {
|
|
const next = await iterator.next();
|
|
|
|
if (next.done) {
|
|
break;
|
|
}
|
|
|
|
acc = await accumulator(acc, next.value);
|
|
}
|
|
|
|
if (resultSelector) {
|
|
return await resultSelector(acc);
|
|
}
|
|
|
|
return acc as unknown as TResult;
|
|
}
|
|
|
|
async #find<TResult>(sorter: MaybeAsyncPredicate<number>, selector?: MaybeAsyncConverter<TElement, TResult>, comparer?: MaybeAsyncComparer<TResult>) {
|
|
const iterator = this.iterator();
|
|
|
|
let next = await iterator.next();
|
|
|
|
if (next.done) {
|
|
throw new Error("Sequence contains no element.")
|
|
}
|
|
|
|
if (!selector) {
|
|
selector = identity as MaybeAsyncConverter<TElement, TResult>;
|
|
}
|
|
|
|
if (!comparer) {
|
|
comparer = operatorCompare;
|
|
}
|
|
|
|
let result = next.value;
|
|
let convertedResult = await selector(result);
|
|
|
|
while (true) {
|
|
next = await iterator.next();
|
|
|
|
if (next.done) {
|
|
break;
|
|
}
|
|
|
|
const value = next.value;
|
|
const convertedValue = await selector(value);
|
|
|
|
if (await sorter(await comparer(convertedResult, convertedValue))) {
|
|
result = value;
|
|
convertedResult = convertedValue;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
min(comparer?: MaybeAsyncComparer<TElement>) {
|
|
return this.#find(x => x > 0, undefined, comparer);
|
|
}
|
|
|
|
minBy<TBy>(converter: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>) {
|
|
return this.#find(x => x > 0, converter, comparer);
|
|
}
|
|
|
|
max(comparer?: MaybeAsyncComparer<TElement>) {
|
|
return this.#find(x => x < 0, undefined, comparer);
|
|
}
|
|
|
|
maxBy<TBy>(converter: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>) {
|
|
return this.#find(x => x < 0, converter, comparer);
|
|
}
|
|
|
|
order(comparer?: MaybeAsyncComparer<TElement>): OrderedAsyncSequence<TElement> {
|
|
return new OrderAsyncSequence<TElement>(this, false, comparer);
|
|
}
|
|
|
|
orderBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>): OrderedAsyncSequence<TElement> {
|
|
return new OrderByAsyncSequence<TElement, TBy>(this, false, selector, comparer);
|
|
}
|
|
|
|
orderDescending(comparer?: MaybeAsyncComparer<TElement>): OrderedAsyncSequence<TElement> {
|
|
return new OrderAsyncSequence<TElement>(this, true, comparer);
|
|
}
|
|
|
|
orderByDescending<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>): OrderedAsyncSequence<TElement> {
|
|
return new OrderByAsyncSequence<TElement, TBy>(this, true, selector, comparer);
|
|
}
|
|
|
|
distinct(equater?: MaybeAsyncEquater<TElement>): AsyncSequence<TElement> {
|
|
return new DistinctAsyncSequence<TElement>(this, equater);
|
|
}
|
|
|
|
distinctBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEquater<TBy>): AsyncSequence<TElement> {
|
|
return new DistinctByAsyncSequence<TElement, TBy>(this, selector, equater);
|
|
}
|
|
|
|
union(iterable: MaybeAsyncIterable<TElement>, equater?: MaybeAsyncEquater<TElement>): AsyncSequence<TElement> {
|
|
return new UnionAsyncSequence<TElement>(this, wrap(iterable), equater);
|
|
}
|
|
|
|
unionBy<TBy>(iterable: MaybeAsyncIterable<TElement>, selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEquater<TBy>): AsyncSequence<TElement> {
|
|
return new UnionByAsyncSequence<TElement, TBy>(this, wrap(iterable), selector, equater);
|
|
}
|
|
|
|
except(iterable: MaybeAsyncIterable<TElement>): AsyncSequence<TElement> {
|
|
return new ExceptAsyncSequence<TElement>(this, wrap(iterable));
|
|
}
|
|
|
|
exceptBy<TBy>(iterable: MaybeAsyncIterable<TElement>, selector: MaybeAsyncConverter<TElement, TBy>): AsyncSequence<TElement> {
|
|
return new ExceptByAsyncSequence<TElement, TBy>(this, wrap(iterable), selector);
|
|
}
|
|
|
|
intersect(iterable: MaybeAsyncIterable<TElement>): AsyncSequence<TElement> {
|
|
return new IntersectAsyncSequence<TElement>(this, wrap(iterable));
|
|
}
|
|
|
|
intersectBy<TBy>(iterable: MaybeAsyncIterable<TElement>, selector: MaybeAsyncConverter<TElement, TBy>): AsyncSequence<TElement> {
|
|
return new IntersectByAsyncSequence<TElement, TBy>(this, wrap(iterable), selector);
|
|
}
|
|
|
|
async all(predicate: MaybeAsyncPredicate<TElement>) {
|
|
const n = await this.nonEnumeratedCount();
|
|
|
|
if (n === 0) {
|
|
return false;
|
|
}
|
|
|
|
for await (const element of this) {
|
|
if (!await predicate(element)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
async any(predicate?: MaybeAsyncPredicate<TElement>) {
|
|
const n = await this.nonEnumeratedCount();
|
|
|
|
if (n === 0) {
|
|
return false;
|
|
}
|
|
|
|
if (predicate) {
|
|
for await (const element of this) {
|
|
if (await predicate(element)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
return n < 0 ? !(await this.iterator().next()).done : n > 0;
|
|
}
|
|
|
|
async none(predicate?: MaybeAsyncPredicate<TElement>) {
|
|
const n = await this.nonEnumeratedCount();
|
|
|
|
if (n === 0) {
|
|
return true;
|
|
}
|
|
|
|
if (predicate) {
|
|
for await (const element of this) {
|
|
if (predicate(element)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return n < 0 && (await this.iterator().next()).done === true;
|
|
}
|
|
|
|
skip(n: number): AsyncSequence<TElement> {
|
|
if (n < 0) {
|
|
throw new Error("Cannot skip a negative number of elements.");
|
|
}
|
|
|
|
return n === 0 ? this : new SkipAsyncSequence<TElement>(this, n);
|
|
}
|
|
|
|
skipLast(n: number): AsyncSequence<TElement> {
|
|
if (n < 0) {
|
|
throw new Error("Cannot skip a negative number of elements.");
|
|
}
|
|
|
|
return n === 0 ? this : new SkipLastAsyncSequence<TElement>(this, n);
|
|
}
|
|
|
|
skipWhile(predicate: MaybeAsyncPredicate<TElement>): AsyncSequence<TElement> {
|
|
return new SkipWhileAsyncSequence<TElement>(this, predicate);
|
|
}
|
|
|
|
take(n: number): AsyncSequence<TElement> {
|
|
if (n < 0) {
|
|
throw new Error("Cannot take a negative number of elements.");
|
|
}
|
|
|
|
return n === 0 ? empty<TElement>() : new TakeAsyncSequence<TElement>(this, n);
|
|
}
|
|
|
|
takeLast(n: number): AsyncSequence<TElement> {
|
|
if (n < 0) {
|
|
throw new Error("Cannot take a negative number of elements.");
|
|
}
|
|
|
|
return n === 0 ? empty<TElement>() : new TakeLastAsyncSequence<TElement>(this, n);
|
|
}
|
|
|
|
takeWhile(predicate: MaybeAsyncPredicate<TElement>): AsyncSequence<TElement> {
|
|
return new TakeWhileAsyncSequence<TElement>(this, predicate);
|
|
}
|
|
|
|
peek(action: MaybeAsyncAction<TElement>): AsyncSequence<TElement> {
|
|
return new PeekAsyncSequence(this, action);
|
|
}
|
|
|
|
async forEach(action: MaybeAsyncAction<TElement>) {
|
|
for await (const element of this) {
|
|
await action(element);
|
|
}
|
|
}
|
|
|
|
zip<TOther>(iterable: MaybeAsyncIterable<TOther>): AsyncSequence<[Awaited<TElement>, Awaited<TOther>]> {
|
|
return new ZippedAsyncSequence<TElement, TOther>(this, wrap(iterable));
|
|
}
|
|
|
|
indexex(): AsyncSequence<[number, Awaited<TElement>]> {
|
|
return new IndexedAsyncSequence<TElement>(this);
|
|
}
|
|
|
|
reversed(): AsyncSequence<TElement> {
|
|
return new ReversedAsyncSequence<TElement>(this);
|
|
}
|
|
|
|
chunked(size: number): AsyncSequence<TElement[]> {
|
|
if (size <= 0) {
|
|
throw new Error("Chunk size must be positive.");
|
|
}
|
|
|
|
return new ChunkedAsyncSequence<TElement>(this, size);
|
|
}
|
|
|
|
async random(options?: AsyncRandomOptions<TElement> | undefined): Promise<TElement | undefined> {
|
|
return (await getRandomElementAsync(this, options)).element;
|
|
}
|
|
|
|
cached(): AsyncSequence<TElement> {
|
|
return new CacheAsyncSequence<TElement>(this);
|
|
}
|
|
|
|
async toArray() {
|
|
const array: TElement[] = [];
|
|
|
|
for await (const element of this) {
|
|
array.push(element);
|
|
}
|
|
|
|
return array;
|
|
}
|
|
|
|
async toMap<TKey, TValue>(keySelector: MaybeAsyncConverter<TElement, TKey>, valueSelector: MaybeAsyncConverter<TElement, TValue>) {
|
|
const map = new Map<TKey, TValue>();
|
|
|
|
for await (const element of this) {
|
|
const key = await keySelector(element);
|
|
const value = await valueSelector(element);
|
|
|
|
map.set(key, value);
|
|
}
|
|
|
|
return map;
|
|
}
|
|
|
|
async toSet() {
|
|
const set = new Set<TElement>();
|
|
|
|
for await (const element of this) {
|
|
set.add(element);
|
|
}
|
|
|
|
return set;
|
|
}
|
|
|
|
async toObject<TValue>(keySelector: MaybeAsyncConverter<TElement, PropertyKey>, valueSelector: MaybeAsyncConverter<TElement, TValue>) {
|
|
const obj: Record<PropertyKey, TValue> = {};
|
|
|
|
for await (const element of this) {
|
|
const key = await keySelector(element);
|
|
const value = await valueSelector(element);
|
|
|
|
obj[key] = value;
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
async collect<TResult>(collector: Collector<TElement, any, TResult>) {
|
|
const acc = collector.initialize();
|
|
|
|
for await (const e of this) {
|
|
collector.accumulate(acc, e);
|
|
}
|
|
|
|
return collector.finalize(acc);
|
|
}
|
|
}
|
|
|
|
export class DelegatedAsyncSequence<TElement> extends AsyncSequenceMarker implements AsyncSequence<TElement> {
|
|
#sequence: AsyncSequence<TElement>;
|
|
|
|
constructor(sequence: AsyncSequence<TElement>) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
}
|
|
|
|
get sequence() {
|
|
return this.#sequence;
|
|
}
|
|
|
|
protected set sequence(value: AsyncSequence<TElement>) {
|
|
this.#sequence = value;
|
|
}
|
|
|
|
[Symbol.asyncIterator]() {
|
|
return this.iterator();
|
|
}
|
|
|
|
iterator() {
|
|
return this.#sequence.iterator();
|
|
}
|
|
|
|
apply<TResult>(pipeline: (sequence: AsyncSequence<TElement>) => TResult) {
|
|
return this.#sequence.apply(pipeline);
|
|
}
|
|
|
|
count(predicate?: ((obj: TElement) => MaybePromise<boolean>) | undefined): Promise<number> {
|
|
return this.#sequence.count(predicate);
|
|
}
|
|
|
|
nonEnumeratedCount(): Promise<number> {
|
|
return this.#sequence.nonEnumeratedCount();
|
|
}
|
|
|
|
fastCount(): Promise<number> {
|
|
return this.#sequence.fastCount();
|
|
}
|
|
|
|
maxCount(): Promise<number> {
|
|
return this.#sequence.maxCount();
|
|
}
|
|
|
|
select<TResult>(selector: (obj: TElement) => MaybePromise<TResult>): AsyncSequence<TResult> {
|
|
return this.#sequence.select(selector);
|
|
}
|
|
|
|
selectMany<TResult>(selector: (obj: TElement) => MaybePromise<MaybeAsyncIterable<TResult>>): AsyncSequence<TResult> {
|
|
return this.#sequence.selectMany(selector);
|
|
}
|
|
|
|
where(predicate: (obj: TElement) => MaybePromise<boolean>): AsyncSequence<TElement> {
|
|
return this.#sequence.where(predicate);
|
|
}
|
|
|
|
groupBy<TKey>(keySelector: (obj: TElement) => MaybePromise<TKey>, elementSelector?: undefined, keyComparer?: ((first: TKey, second: TKey) => MaybePromise<boolean>) | undefined): AsyncSequence<GroupedAsyncSequence<TKey, TElement>>;
|
|
groupBy<TKey, TResult>(keySelector: (obj: TElement) => MaybePromise<TKey>, elementSelector: (obj: TElement) => MaybePromise<TResult>, keyComparer?: ((first: TKey, second: TKey) => MaybePromise<boolean>) | undefined): AsyncSequence<GroupedAsyncSequence<TKey, TResult>>;
|
|
groupBy(keySelector: any, elementSelector?: any, keyComparer?: any) {
|
|
return this.#sequence.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): AsyncSequence<[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): AsyncSequence<TResult>;
|
|
join(iterable: any, firstKeySelector: any, secondKeySelector: any, resultSelector?: any, keyComparer?: any) {
|
|
return this.#sequence.join(iterable, firstKeySelector, secondKeySelector, resultSelector, keyComparer);
|
|
}
|
|
|
|
groupJoin<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): AsyncSequence<GroupedAsyncSequence<TElement, TOther>>;
|
|
groupJoin<TOther, TKey, TResult>(iterable: MaybeAsyncIterable<TOther>, firstKeySelector: (obj: TElement) => MaybePromise<TKey>, secondKeySelector: (obj: TOther) => MaybePromise<TKey>, resultSelector: (first: TElement, second: AsyncSequence<TOther>) => MaybePromise<TResult>, keyComparer?: ((first: TKey, second: TKey) => MaybePromise<boolean>) | undefined): AsyncSequence<TResult>;
|
|
groupJoin(iterable: any, firstKeySelector: any, secondKeySelector: any, resultSelector?: any, keyComparer?: any) {
|
|
return this.#sequence.groupJoin(iterable, firstKeySelector, secondKeySelector, resultSelector, keyComparer);
|
|
}
|
|
|
|
contains(obj: TElement, equater?: ((first: TElement, second: TElement) => MaybePromise<boolean>) | undefined): Promise<boolean> {
|
|
return this.#sequence.contains(obj, equater);
|
|
}
|
|
|
|
sequenceEquals(iterable: MaybeAsyncIterable<TElement>, equater?: ((first: TElement, second: TElement) => MaybePromise<boolean>) | undefined): Promise<boolean> {
|
|
return this.#sequence.sequenceEquals(iterable, equater);
|
|
}
|
|
|
|
append(obj: TElement): AsyncSequence<TElement> {
|
|
return this.#sequence.append(obj);
|
|
}
|
|
|
|
prepend(obj: TElement): AsyncSequence<TElement> {
|
|
return this.#sequence.prepend(obj);
|
|
}
|
|
|
|
remove(obj: TElement, all?: boolean | undefined, equater?: ((first: TElement, second: TElement) => MaybePromise<boolean>) | undefined): AsyncSequence<TElement> {
|
|
return this.#sequence.remove(obj, all, equater);
|
|
}
|
|
|
|
concat(...iterables: MaybeAsyncIterable<TElement>[]): AsyncSequence<TElement> {
|
|
return this.#sequence.concat(...iterables);
|
|
}
|
|
|
|
first(predicate?: ((obj: TElement) => MaybePromise<boolean>) | undefined): Promise<TElement> {
|
|
return this.#sequence.first(predicate);
|
|
}
|
|
|
|
firstOrDefault(predicate?: ((obj: TElement) => MaybePromise<boolean>) | undefined, def?: TElement | undefined): Promise<TElement | undefined> {
|
|
return this.#sequence.firstOrDefault(predicate, def);
|
|
}
|
|
|
|
last(predicate?: ((obj: TElement) => MaybePromise<boolean>) | undefined): Promise<TElement> {
|
|
return this.#sequence.last(predicate);
|
|
}
|
|
|
|
lastOrDefault(predicate?: ((obj: TElement) => MaybePromise<boolean>) | undefined, def?: TElement | undefined): Promise<TElement | undefined> {
|
|
return this.#sequence.lastOrDefault(predicate, def);
|
|
}
|
|
|
|
single(predicate?: ((obj: TElement) => MaybePromise<boolean>) | undefined): Promise<TElement> {
|
|
return this.#sequence.single(predicate);
|
|
}
|
|
|
|
singleOrDefault(predicate?: ((obj: TElement) => MaybePromise<boolean>) | undefined, def?: TElement | undefined): Promise<TElement | undefined> {
|
|
return this.#sequence.singleOrDefault(predicate, def);
|
|
}
|
|
|
|
elementAt(index: number): Promise<TElement> {
|
|
return this.#sequence.elementAt(index);
|
|
}
|
|
|
|
elementAtOrDefault(index: number, def?: TElement | undefined): Promise<TElement | undefined> {
|
|
return this.#sequence.elementAtOrDefault(index, def);
|
|
}
|
|
|
|
aggregate(accumulator: (acc: TElement, obj: TElement) => MaybePromise<TElement>): Promise<TElement>;
|
|
aggregate<TAccumulator>(accumulator: (acc: TAccumulator, obj: TElement) => MaybePromise<TAccumulator>, seed?: TAccumulator | undefined): Promise<TAccumulator>;
|
|
aggregate<TAccumulator, TResult>(accumulator: (acc: TAccumulator, obj: TElement) => MaybePromise<TAccumulator>, seed?: TAccumulator | undefined, resultSelector?: ((obj: TAccumulator) => MaybePromise<TResult>) | undefined): Promise<TResult>;
|
|
aggregate(accumulator: any, seed?: any, resultSelector?: any) {
|
|
return this.#sequence.aggregate(accumulator, seed, resultSelector);
|
|
}
|
|
|
|
min(): Promise<TElement> {
|
|
return this.#sequence.min();
|
|
}
|
|
|
|
minBy<TBy>(selector: (obj: TElement) => MaybePromise<TBy>): Promise<TElement> {
|
|
return this.#sequence.minBy(selector);
|
|
}
|
|
|
|
max(): Promise<TElement> {
|
|
return this.#sequence.max();
|
|
}
|
|
|
|
maxBy<TBy>(selector: (obj: TElement) => MaybePromise<TBy>): Promise<TElement> {
|
|
return this.#sequence.maxBy(selector);
|
|
}
|
|
|
|
order(comparer?: ((first: TElement, second: TElement) => MaybePromise<number>) | undefined): AsyncSequence<TElement> {
|
|
return this.#sequence.order(comparer);
|
|
}
|
|
|
|
orderBy<TBy>(selector: (obj: TElement) => MaybePromise<TBy>, comparer?: ((first: TBy, second: TBy) => MaybePromise<number>) | undefined): AsyncSequence<TElement> {
|
|
return this.#sequence.orderBy(selector, comparer);
|
|
}
|
|
|
|
orderDescending(comparer?: ((first: TElement, second: TElement) => MaybePromise<number>) | undefined): AsyncSequence<TElement> {
|
|
return this.#sequence.orderDescending(comparer);
|
|
}
|
|
|
|
orderByDescending<TBy>(selector: (obj: TElement) => MaybePromise<TBy>, comparer?: ((first: TBy, second: TBy) => MaybePromise<number>) | undefined): AsyncSequence<TElement> {
|
|
return this.#sequence.orderByDescending(selector, comparer);
|
|
}
|
|
|
|
distinct(equater?: ((first: TElement, second: TElement) => MaybePromise<boolean>) | undefined): AsyncSequence<TElement> {
|
|
return this.#sequence.distinct(equater);
|
|
}
|
|
|
|
distinctBy<TBy>(selector: (obj: TElement) => MaybePromise<TBy>, equater?: ((first: TBy, second: TBy) => MaybePromise<boolean>) | undefined): AsyncSequence<TElement> {
|
|
return this.#sequence.distinctBy(selector, equater);
|
|
}
|
|
|
|
union(iterable: MaybeAsyncIterable<TElement>, equater?: ((first: TElement, second: TElement) => MaybePromise<boolean>) | undefined): AsyncSequence<TElement> {
|
|
return this.#sequence.union(iterable, equater);
|
|
}
|
|
|
|
unionBy<TBy>(iterable: MaybeAsyncIterable<TElement>, selector: (obj: TElement) => MaybePromise<TBy>, equater?: ((first: TBy, second: TBy) => MaybePromise<boolean>) | undefined): AsyncSequence<TElement> {
|
|
return this.#sequence.unionBy(iterable, selector, equater);
|
|
}
|
|
|
|
except(iterable: MaybeAsyncIterable<TElement>, equater?: ((first: TElement, second: TElement) => MaybePromise<boolean>) | undefined): AsyncSequence<TElement> {
|
|
return this.#sequence.except(iterable, equater);
|
|
}
|
|
|
|
exceptBy<TBy>(iterable: MaybeAsyncIterable<TElement>, selector: (obj: TElement) => MaybePromise<TBy>, equater?: ((first: TBy, second: TBy) => MaybePromise<boolean>) | undefined): AsyncSequence<TElement> {
|
|
return this.#sequence.exceptBy(iterable, selector, equater);
|
|
}
|
|
|
|
intersect(iterable: MaybeAsyncIterable<TElement>, equater?: ((first: TElement, second: TElement) => MaybePromise<boolean>) | undefined): AsyncSequence<TElement> {
|
|
return this.#sequence.intersect(iterable, equater);
|
|
}
|
|
|
|
intersectBy<TBy>(iterable: MaybeAsyncIterable<TElement>, selector: (obj: TElement) => MaybePromise<TBy>, equater?: ((first: TBy, second: TBy) => MaybePromise<boolean>) | undefined): AsyncSequence<TElement> {
|
|
return this.#sequence.intersectBy(iterable, selector, equater);
|
|
}
|
|
|
|
all(predicate: (obj: TElement) => MaybePromise<boolean>): Promise<boolean> {
|
|
return this.#sequence.all(predicate);
|
|
}
|
|
|
|
any(predicate: (obj: TElement) => MaybePromise<boolean>): Promise<boolean>;
|
|
any(): Promise<boolean>;
|
|
any(predicate?: any) {
|
|
return this.#sequence.any(predicate);
|
|
}
|
|
|
|
none(predicate: Predicate<TElement>): Promise<boolean>;
|
|
none(): Promise<boolean>;
|
|
none(predicate?: any) {
|
|
return this.#sequence.none(predicate);
|
|
}
|
|
|
|
skip(n: number): AsyncSequence<TElement> {
|
|
return this.#sequence.skip(n);
|
|
}
|
|
|
|
skipLast(n: number): AsyncSequence<TElement> {
|
|
return this.#sequence.skipLast(n);
|
|
}
|
|
|
|
skipWhile(condition: (obj: TElement) => MaybePromise<boolean>): AsyncSequence<TElement> {
|
|
return this.#sequence.skipWhile(condition);
|
|
}
|
|
|
|
take(n: number): AsyncSequence<TElement> {
|
|
return this.#sequence.take(n);
|
|
}
|
|
|
|
takeLast(n: number): AsyncSequence<TElement> {
|
|
return this.#sequence.takeLast(n);
|
|
}
|
|
|
|
takeWhile(condition: (obj: TElement) => MaybePromise<boolean>): AsyncSequence<TElement> {
|
|
return this.#sequence.takeWhile(condition);
|
|
}
|
|
|
|
peek(action: (obj: TElement) => MaybePromise<void>): AsyncSequence<TElement> {
|
|
return this.#sequence.peek(action);
|
|
}
|
|
|
|
forEach(action: (obj: TElement) => MaybePromise<void>): Promise<void> {
|
|
return this.#sequence.forEach(action);
|
|
}
|
|
|
|
zip<TOther>(iterable: MaybeAsyncIterable<TOther>): AsyncSequence<[Awaited<TElement>, Awaited<TOther>]> {
|
|
return this.#sequence.zip(iterable);
|
|
}
|
|
|
|
indexex(): AsyncSequence<[number, Awaited<TElement>]> {
|
|
return this.#sequence.indexex();
|
|
}
|
|
|
|
reversed(): AsyncSequence<TElement> {
|
|
return this.#sequence.reversed();
|
|
}
|
|
|
|
chunked(size: number): AsyncSequence<TElement[]> {
|
|
return this.#sequence.chunked(size);
|
|
}
|
|
|
|
random(options?: AsyncRandomOptions<TElement> | undefined): Promise<TElement | undefined> {
|
|
return this.#sequence.random(options);
|
|
}
|
|
|
|
cached(): AsyncSequence<TElement> {
|
|
return this.#sequence.cached();
|
|
}
|
|
|
|
toArray(): Promise<TElement[]> {
|
|
return this.#sequence.toArray();
|
|
}
|
|
|
|
toMap<TKey, TValue>(keySelector: (obj: TElement) => MaybePromise<TKey>, valueSelector: (obj: TElement) => MaybePromise<TValue>): Promise<Map<TKey, TValue>> {
|
|
return this.#sequence.toMap(keySelector, valueSelector);
|
|
}
|
|
|
|
toSet(): Promise<Set<TElement>> {
|
|
return this.#sequence.toSet();
|
|
}
|
|
|
|
toObject<TValue>(keySelector: (obj: TElement) => MaybePromise<PropertyKey>, valueSelector: (obj: TElement) => MaybePromise<TValue>): Promise<Record<PropertyKey, TValue>> {
|
|
return this.#sequence.toObject(keySelector, valueSelector);
|
|
}
|
|
|
|
collect<TResult>(collector: Collector<TElement, any, TResult>): Promise<TResult> {
|
|
return this.#sequence.collect(collector);
|
|
}
|
|
}
|
|
|
|
export class GroupedAsyncSequenceImpl<TElement, TKey> extends DelegatedAsyncSequence<TElement> implements GroupedAsyncSequence<TKey, TElement> {
|
|
readonly #key: TKey;
|
|
|
|
constructor(key: TKey, grouping: AsyncSequence<TElement>) {
|
|
super(grouping);
|
|
|
|
this.#key = key;
|
|
}
|
|
|
|
public get key() {
|
|
return this.#key;
|
|
}
|
|
}
|
|
|
|
abstract class BaseOrderedAsyncSequence<TElement> extends BaseAsyncSequence<TElement> implements OrderedAsyncSequence<TElement> {
|
|
readonly #sequence: AsyncSequence<TElement>;
|
|
readonly #sorter: MaybeAsyncComparer<TElement>;
|
|
readonly #descending: boolean;
|
|
|
|
constructor(sequence: AsyncSequence<TElement>, sorter: MaybeAsyncComparer<TElement>, descending: boolean) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#sorter = sorter;
|
|
this.#descending = descending;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
return await this.#sequence.nonEnumeratedCount();
|
|
}
|
|
|
|
override async maxCount() {
|
|
return await this.#sequence.maxCount();
|
|
}
|
|
|
|
get comparer() {
|
|
return this.#sorter;
|
|
}
|
|
|
|
thenSelf(comparer?: MaybeAsyncComparer<TElement>): OrderedAsyncSequence<TElement> {
|
|
return new ThenOrderAsyncSequence(this, false, comparer);
|
|
}
|
|
|
|
thenBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>): OrderedAsyncSequence<TElement> {
|
|
return new ThenOrderByAsyncSequence<TElement, TBy>(this, false, selector, comparer);
|
|
}
|
|
|
|
thenSelfDescending(comparer?: MaybeAsyncComparer<TElement>): OrderedAsyncSequence<TElement> {
|
|
return new ThenOrderAsyncSequence(this, true, comparer);
|
|
}
|
|
|
|
thenByDescending<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>): OrderedAsyncSequence<TElement> {
|
|
return new ThenOrderByAsyncSequence<TElement, TBy>(this, true, selector, comparer);
|
|
}
|
|
|
|
override async *iterator() {
|
|
const arr: TElement[] = [];
|
|
|
|
for await (const obj of this.#sequence) {
|
|
arr.push(obj);
|
|
}
|
|
|
|
await selectionSorter.sort(arr, this.#descending, this.#sorter);
|
|
|
|
yield* arr;
|
|
}
|
|
}
|
|
|
|
export class EmptyAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
static readonly INSTANCE = new EmptyAsyncSequence<any>();
|
|
|
|
override async nonEnumeratedCount() {
|
|
return 0;
|
|
}
|
|
|
|
override async *iterator() {
|
|
|
|
}
|
|
}
|
|
|
|
export class RangeAsyncSequence extends BaseAsyncSequence<number> {
|
|
readonly #min: number;
|
|
readonly #max: number;
|
|
readonly #step: number;
|
|
|
|
constructor(min: number, max: number, step: number) {
|
|
super();
|
|
|
|
this.#min = min;
|
|
this.#max = max;
|
|
this.#step = step;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
return Math.ceil((this.#max - this.#min) / this.#step);
|
|
}
|
|
|
|
override async *iterator() {
|
|
for (let i = this.#min; i < this.#max; i += this.#step) {
|
|
yield i;
|
|
}
|
|
}
|
|
}
|
|
|
|
export class RepeatAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #value: T;
|
|
readonly #count: number;
|
|
|
|
constructor(value: T, count: number) {
|
|
super();
|
|
|
|
this.#value = value;
|
|
this.#count = count;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
return this.#count;
|
|
}
|
|
|
|
override async *iterator() {
|
|
let i = this.#count;
|
|
|
|
while (i-- > 0) {
|
|
yield this.#value;
|
|
}
|
|
}
|
|
}
|
|
|
|
export class RepeatForeverAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #value: T;
|
|
|
|
constructor(value: T) {
|
|
super();
|
|
|
|
this.#value = value;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
return Infinity;
|
|
}
|
|
|
|
override async *iterator() {
|
|
while (true) {
|
|
yield this.#value;
|
|
}
|
|
}
|
|
}
|
|
|
|
export class WrappedObjectAsync<T> extends BaseAsyncSequence<T> {
|
|
readonly #obj: T | PromiseLike<T>;
|
|
|
|
constructor(obj: T | PromiseLike<T>) {
|
|
super();
|
|
|
|
this.#obj = obj;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
return 1;
|
|
}
|
|
|
|
override async *iterator() {
|
|
yield this.#obj;
|
|
}
|
|
}
|
|
|
|
export class WrappedArrayAsync<T> extends BaseAsyncSequence<T> {
|
|
readonly #array: (T | PromiseLike<T>)[];
|
|
|
|
constructor(array: (T | PromiseLike<T>)[]) {
|
|
super();
|
|
|
|
this.#array = array;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
return this.#array.length;
|
|
}
|
|
|
|
override async *iterator() {
|
|
yield* this.#array;
|
|
}
|
|
}
|
|
|
|
export class WrappedArrayLikeAsync<T> extends BaseAsyncSequence<T> {
|
|
readonly #arrayLike: ArrayLike<T | PromiseLike<T>>;
|
|
|
|
constructor(arrayLike: ArrayLike<T | PromiseLike<T>>) {
|
|
super();
|
|
|
|
this.#arrayLike = arrayLike;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
return this.#arrayLike.length;
|
|
}
|
|
|
|
override async *iterator() {
|
|
for (let i = 0; i < this.#arrayLike.length; i++) {
|
|
yield this.#arrayLike[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
export class WrappedAsyncIterable<T> extends BaseAsyncSequence<T> {
|
|
readonly #iterable: AsyncIterable<T>;
|
|
|
|
constructor(iterable: AsyncIterable<T>) {
|
|
super();
|
|
|
|
this.#iterable = iterable;
|
|
}
|
|
|
|
override async *iterator() {
|
|
yield* this.#iterable;
|
|
}
|
|
}
|
|
|
|
export class GeneratorAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #generator: () => AsyncGenerator<T>;
|
|
|
|
constructor(generator: () => AsyncGenerator<T>) {
|
|
super();
|
|
|
|
this.#generator = generator;
|
|
}
|
|
|
|
override async *iterator() {
|
|
yield* this.#generator();
|
|
}
|
|
}
|
|
|
|
export class FunctionAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #f: () => MaybePromise<T>;
|
|
|
|
constructor(f: () => MaybePromise<T>) {
|
|
super();
|
|
|
|
this.#f = f;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
return Infinity;
|
|
}
|
|
|
|
override async *iterator() {
|
|
while (true) {
|
|
yield await this.#f();
|
|
}
|
|
}
|
|
}
|
|
|
|
export class WrappedSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #sequence: Sequence<T>;
|
|
|
|
constructor(sequence: Sequence<T>) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
return this.#sequence.nonEnumeratedCount();
|
|
}
|
|
|
|
override async fastCount() {
|
|
return this.#sequence.fastCount();
|
|
}
|
|
|
|
override async maxCount() {
|
|
return this.#sequence.maxCount();
|
|
}
|
|
|
|
override async *iterator() {
|
|
yield* this.#sequence;
|
|
}
|
|
}
|
|
|
|
export class ConcatAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #sequences: Iterable<AsyncSequence<T>>;
|
|
|
|
constructor(sequences: Iterable<AsyncSequence<T>>) {
|
|
super();
|
|
|
|
this.#sequences = sequences;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
let n = 0;
|
|
|
|
for (const iterable of this.#sequences) {
|
|
const m = await iterable.nonEnumeratedCount();
|
|
|
|
if (m < 0) {
|
|
return -1;
|
|
}
|
|
|
|
n += m;
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
override async *iterator() {
|
|
for (const sequence of this.#sequences) {
|
|
yield* sequence;
|
|
}
|
|
}
|
|
}
|
|
|
|
export class DistinctAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
readonly #equater: MaybeAsyncEquater<T> | undefined;
|
|
|
|
constructor(sequence: AsyncSequence<T>, equater?: MaybeAsyncEquater<T>) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#equater = equater;
|
|
}
|
|
|
|
override async *iterator() {
|
|
const set = createAsyncEqualitySet(this.#equater);
|
|
|
|
for await (const obj of this.#sequence) {
|
|
if (await set.add(obj)) {
|
|
yield obj;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export class DistinctByAsyncSequence<T, U> extends BaseAsyncSequence<T> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
readonly #selector: MaybeAsyncConverter<T, U>;
|
|
readonly #equater: MaybeAsyncEquater<U> | undefined;
|
|
|
|
constructor(sequence: AsyncSequence<T>, selector: MaybeAsyncConverter<T, U>, equater?: MaybeAsyncEquater<U>) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#selector = selector;
|
|
this.#equater = equater;
|
|
}
|
|
|
|
override async *iterator() {
|
|
const set = createAsyncEqualitySet(this.#equater);
|
|
|
|
for await (const obj of this.#sequence) {
|
|
if (await set.add(await this.#selector(obj))) {
|
|
yield obj;
|
|
}
|
|
}
|
|
|
|
set.clear();
|
|
}
|
|
}
|
|
|
|
export class FilterAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
readonly #predicate: MaybeAsyncPredicate<T>;
|
|
|
|
constructor(sequence: AsyncSequence<T>, predicate: MaybeAsyncPredicate<T>) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#predicate = predicate;
|
|
}
|
|
|
|
override async *iterator() {
|
|
for await (const obj of this.#sequence) {
|
|
if (await this.#predicate(obj)) {
|
|
yield obj;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export class FlatMapperAsyncSequence<T, U> extends BaseAsyncSequence<U> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
readonly #converter: MaybeAsyncConverter<T, MaybeAsyncIterable<U>>;
|
|
|
|
constructor(sequence: AsyncSequence<T>, converter: MaybeAsyncConverter<T, MaybeAsyncIterable<U>>) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#converter = converter;
|
|
}
|
|
|
|
override async *iterator() {
|
|
for await (const obj of this.#sequence) {
|
|
yield* await this.#converter(obj);
|
|
}
|
|
}
|
|
}
|
|
|
|
export class IndexedAsyncSequence<T> extends BaseAsyncSequence<[number, Awaited<T>]> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
|
|
constructor(sequence: AsyncSequence<T>) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
}
|
|
|
|
override async *iterator() {
|
|
let i = 0;
|
|
|
|
for await (const obj of this.#sequence) {
|
|
yield [i++, obj] as [number, Awaited<T>];
|
|
}
|
|
}
|
|
}
|
|
|
|
export class MapperAsyncSequence<T, U> extends BaseAsyncSequence<U> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
readonly #converter: MaybeAsyncConverter<T, U>;
|
|
|
|
constructor(sequence: AsyncSequence<T>, converter: MaybeAsyncConverter<T, U>) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#converter = converter;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
return await this.#sequence.nonEnumeratedCount();
|
|
}
|
|
|
|
override async *iterator() {
|
|
for await (const obj of this.#sequence) {
|
|
yield await this.#converter(obj);
|
|
}
|
|
}
|
|
}
|
|
|
|
export class SkipWhileAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
readonly #predicate: MaybeAsyncPredicate<T>;
|
|
|
|
constructor(sequence: AsyncSequence<T>, predicate: MaybeAsyncPredicate<T>) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#predicate = predicate;
|
|
}
|
|
|
|
override async *iterator() {
|
|
const iterator = this.#sequence.iterator();
|
|
|
|
while (true) {
|
|
const next = await iterator.next();
|
|
|
|
if (next.done) {
|
|
return;
|
|
}
|
|
|
|
if (await this.#predicate(next.value)) {
|
|
continue;
|
|
}
|
|
|
|
yield next.value;
|
|
break;
|
|
}
|
|
|
|
yield* asAsyncGenerator(iterator);
|
|
}
|
|
}
|
|
|
|
export class SkipLastAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
readonly #n: number;
|
|
|
|
constructor(sequence: AsyncSequence<T>, n: number) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#n = n;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
const n = await this.#sequence.nonEnumeratedCount();
|
|
return n < 0 ? -1 : Math.max(0, n - this.#n);
|
|
}
|
|
|
|
override async *iterator() {
|
|
const iterator = this.#sequence.iterator();
|
|
const buffer = new Array<T>(this.#n); // n > 0
|
|
let i = 0;
|
|
|
|
do {
|
|
const next = await iterator.next();
|
|
|
|
if (next.done) {
|
|
return;
|
|
}
|
|
|
|
buffer[i++] = next.value;
|
|
} while (i < this.#n);
|
|
|
|
i = 0;
|
|
|
|
for await (const obj of asAsyncGenerator(iterator)) {
|
|
yield buffer[i];
|
|
buffer[i] = obj;
|
|
i = (i + 1) % this.#n;
|
|
}
|
|
}
|
|
}
|
|
|
|
export class SkipAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
readonly #n: number;
|
|
|
|
constructor(sequence: AsyncSequence<T>, n: number) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#n = n;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
const n = await this.#sequence.nonEnumeratedCount();
|
|
return n < 0 ? -1 : Math.max(0, n - this.#n);
|
|
}
|
|
|
|
override async *iterator() {
|
|
const iterator = this.#sequence.iterator();
|
|
let i = 0;
|
|
|
|
do {
|
|
if ((await iterator.next()).done) {
|
|
return;
|
|
}
|
|
|
|
i++;
|
|
} while (i < this.#n);
|
|
|
|
yield* asAsyncGenerator(iterator);
|
|
}
|
|
}
|
|
|
|
export class TakeWhileAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
readonly #predicate: MaybeAsyncPredicate<T>;
|
|
|
|
constructor(sequence: AsyncSequence<T>, predicate: MaybeAsyncPredicate<T>) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#predicate = predicate;
|
|
}
|
|
|
|
override async *iterator() {
|
|
for await (const obj of this.#sequence) {
|
|
if (!await this.#predicate(obj)) {
|
|
return;
|
|
}
|
|
|
|
yield obj;
|
|
}
|
|
}
|
|
}
|
|
|
|
export class TakeLastAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
readonly #n: number;
|
|
|
|
constructor(sequence: AsyncSequence<T>, n: number) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#n = n;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
const n = await this.#sequence.nonEnumeratedCount();
|
|
return n < 0 ? -1 : Math.min(this.#n, n);
|
|
}
|
|
|
|
override async *iterator() {
|
|
const queue = createQueue<T>(this.#n);
|
|
|
|
for await (const obj of this.#sequence) {
|
|
queue.enqueue(obj);
|
|
}
|
|
|
|
yield* queue;
|
|
}
|
|
}
|
|
|
|
export class TakeAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
readonly #n: number;
|
|
|
|
constructor(sequence: AsyncSequence<T>, n: number) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#n = n;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
const n = await this.#sequence.nonEnumeratedCount();
|
|
return n < 0 ? -1 : Math.min(this.#n, n);
|
|
}
|
|
|
|
override async *iterator() {
|
|
const iterator = this.#sequence.iterator();
|
|
let i = this.#n;
|
|
|
|
while (i > 0) {
|
|
const next = await iterator.next();
|
|
|
|
if (next.done) {
|
|
return;
|
|
}
|
|
|
|
yield next.value as T;
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
|
|
export class OrderAsyncSequence<T> extends BaseOrderedAsyncSequence<T> {
|
|
constructor(sequence: AsyncSequence<T>, descending: boolean, sorter?: MaybeAsyncComparer<T>) {
|
|
super(sequence, sorter ?? defaultArrayComparer, descending);
|
|
}
|
|
}
|
|
|
|
export class OrderByAsyncSequence<T, U> extends BaseOrderedAsyncSequence<T> {
|
|
constructor(sequence: AsyncSequence<T>, descending: boolean, selector: MaybeAsyncConverter<T, U>, sorter?: MaybeAsyncComparer<U>) {
|
|
super(sequence, OrderByAsyncSequence.#createSorter(selector, sorter), descending);
|
|
}
|
|
|
|
static #createSorter<T, U>(selector: MaybeAsyncConverter<T, U>, sorter?: MaybeAsyncComparer<U>) {
|
|
sorter ??= defaultArrayComparer;
|
|
return async (a: T, b: T) => sorter(await selector(a), await selector(b));
|
|
}
|
|
}
|
|
|
|
export class ThenOrderAsyncSequence<T> extends BaseOrderedAsyncSequence<T> {
|
|
constructor(sequence: OrderedAsyncSequence<T>, descending: boolean, sorter?: MaybeAsyncComparer<T>) {
|
|
super(sequence, combineAsyncComparers(sequence.comparer ?? defaultArrayComparer, sorter ?? defaultArrayComparer), descending);
|
|
}
|
|
}
|
|
|
|
export class ThenOrderByAsyncSequence<T, U> extends BaseOrderedAsyncSequence<T> {
|
|
constructor(sequence: OrderedAsyncSequence<T>, descending: boolean, selector: MaybeAsyncConverter<T, U>, sorter?: MaybeAsyncComparer<U>) {
|
|
super(sequence, ThenOrderByAsyncSequence.#createCombinedSorter(sequence.comparer, selector, sorter), descending);
|
|
}
|
|
|
|
static #createCombinedSorter<T, U>(baseSorter: MaybeAsyncComparer<T>, selector: MaybeAsyncConverter<T, U>, sorter?: MaybeAsyncComparer<U>) {
|
|
baseSorter ??= defaultArrayComparer;
|
|
sorter ??= defaultArrayComparer;
|
|
return combineAsyncComparers(baseSorter, async (a: T, b: T) => sorter(await selector(a), await selector(b)));
|
|
}
|
|
}
|
|
|
|
export class AppendAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
readonly #obj: T;
|
|
|
|
constructor(sequence: AsyncSequence<T>, obj: T) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#obj = obj;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
const n = await this.#sequence.nonEnumeratedCount();
|
|
return n < 0 ? -1 : n + 1;
|
|
}
|
|
|
|
override async *iterator() {
|
|
yield* this.#sequence;
|
|
yield this.#obj;
|
|
}
|
|
}
|
|
|
|
export class PrependAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
readonly #obj: T;
|
|
|
|
constructor(sequence: AsyncSequence<T>, obj: T) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#obj = obj;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
const n = await this.#sequence.nonEnumeratedCount();
|
|
return n < 0 ? -1 : n + 1;
|
|
}
|
|
|
|
override async *iterator() {
|
|
yield this.#obj;
|
|
yield* this.#sequence;
|
|
}
|
|
}
|
|
|
|
export class PeekAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
readonly #action: MaybeAsyncAction<T>;
|
|
|
|
constructor(sequence: AsyncSequence<T>, action: MaybeAsyncAction<T>) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#action = action;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
return await this.#sequence.nonEnumeratedCount();
|
|
}
|
|
|
|
override async *iterator() {
|
|
for await (const obj of this.#sequence) {
|
|
await this.#action(obj);
|
|
yield obj;
|
|
}
|
|
}
|
|
}
|
|
|
|
export class ZippedAsyncSequence<T, U> extends BaseAsyncSequence<[Awaited<T>, Awaited<U>]> {
|
|
readonly #first: AsyncSequence<T>;
|
|
readonly #second: AsyncSequence<U>;
|
|
|
|
constructor(first: AsyncSequence<T>, second: AsyncSequence<U>) {
|
|
super();
|
|
|
|
this.#first = first;
|
|
this.#second = second;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
const first = await this.#first.nonEnumeratedCount();
|
|
const second = await this.#second.nonEnumeratedCount();
|
|
|
|
return first < 0 || second < 0 ? -1 : Math.min(first, second);
|
|
}
|
|
|
|
override async *iterator() {
|
|
const firstIterator = this.#first.iterator();
|
|
const secondIterator = this.#second.iterator();
|
|
|
|
while (true) {
|
|
const firstNext = await firstIterator.next();
|
|
const secondNext = await secondIterator.next();
|
|
|
|
if (firstNext.done || secondNext.done) {
|
|
return;
|
|
}
|
|
|
|
yield [firstNext.value, secondNext.value] as [Awaited<T>, Awaited<U>];
|
|
}
|
|
}
|
|
}
|
|
|
|
export class UnionAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #first: AsyncSequence<T>;
|
|
readonly #second: AsyncSequence<T>;
|
|
readonly #equater: MaybeAsyncEquater<T> | undefined;
|
|
|
|
constructor(first: AsyncSequence<T>, second: AsyncSequence<T>, equater?: MaybeAsyncEquater<T>) {
|
|
super();
|
|
|
|
this.#first = first;
|
|
this.#second = second;
|
|
this.#equater = equater;
|
|
}
|
|
|
|
override async *iterator() {
|
|
const set = createAsyncEqualitySet(this.#equater);
|
|
|
|
for await (const obj of this.#first) {
|
|
if (await set.add(obj)) {
|
|
yield obj;
|
|
}
|
|
}
|
|
|
|
for await (const obj of this.#second) {
|
|
if (await set.add(obj)) {
|
|
yield obj;
|
|
}
|
|
}
|
|
|
|
set.clear();
|
|
}
|
|
}
|
|
|
|
export class UnionByAsyncSequence<T, U> extends BaseAsyncSequence<T> {
|
|
readonly #first: AsyncSequence<T>;
|
|
readonly #second: AsyncSequence<T>;
|
|
readonly #selector: MaybeAsyncConverter<T, U>;
|
|
readonly #equater: MaybeAsyncEquater<U> | undefined;
|
|
|
|
constructor(first: AsyncSequence<T>, second: AsyncSequence<T>, selector: MaybeAsyncConverter<T, U>, equater?: MaybeAsyncEquater<U>) {
|
|
super();
|
|
|
|
this.#first = first;
|
|
this.#second = second;
|
|
this.#selector = selector;
|
|
this.#equater = equater;
|
|
}
|
|
|
|
override async *iterator() {
|
|
const set = createAsyncEqualitySet(this.#equater);
|
|
|
|
for await (const obj of this.#first) {
|
|
if (await set.add(await this.#selector(obj))) {
|
|
yield obj;
|
|
}
|
|
}
|
|
|
|
for await (const obj of this.#second) {
|
|
if (await set.add(await this.#selector(obj))) {
|
|
yield obj;
|
|
}
|
|
}
|
|
|
|
set.clear();
|
|
}
|
|
}
|
|
|
|
export class ExceptAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #first: AsyncSequence<T>;
|
|
readonly #second: AsyncSequence<T>;
|
|
readonly #equater: MaybeAsyncEquater<T> | undefined;
|
|
|
|
constructor(first: AsyncSequence<T>, second: AsyncSequence<T>, equater?: MaybeAsyncEquater<T>) {
|
|
super();
|
|
|
|
this.#first = first;
|
|
this.#second = second;
|
|
this.#equater = equater;
|
|
}
|
|
|
|
override async *iterator() {
|
|
const set = createAsyncEqualitySet(this.#equater);
|
|
|
|
for await (const obj of this.#second) {
|
|
await set.add(obj);
|
|
}
|
|
|
|
for await (const obj of this.#first) {
|
|
if (await set.add(obj)) {
|
|
yield obj;
|
|
}
|
|
}
|
|
|
|
set.clear();
|
|
}
|
|
}
|
|
|
|
export class ExceptByAsyncSequence<T, U> extends BaseAsyncSequence<T> {
|
|
readonly #first: AsyncSequence<T>;
|
|
readonly #second: AsyncSequence<T>;
|
|
readonly #selector: MaybeAsyncConverter<T, U>;
|
|
readonly #equater: MaybeAsyncEquater<U> | undefined;
|
|
|
|
constructor(first: AsyncSequence<T>, second: AsyncSequence<T>, selector: MaybeAsyncConverter<T, U>, equater?: MaybeAsyncEquater<U>) {
|
|
super();
|
|
|
|
this.#first = first;
|
|
this.#second = second;
|
|
this.#selector = selector;
|
|
this.#equater = equater;
|
|
}
|
|
|
|
override async *iterator() {
|
|
const set = createAsyncEqualitySet(this.#equater);
|
|
|
|
for await (const obj of this.#second) {
|
|
await set.add(await this.#selector(obj));
|
|
}
|
|
|
|
for await (const obj of this.#first) {
|
|
if (await set.add(await this.#selector(obj))) {
|
|
yield obj;
|
|
}
|
|
}
|
|
|
|
set.clear();
|
|
}
|
|
}
|
|
|
|
export class IntersectAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #first: AsyncSequence<T>;
|
|
readonly #second: AsyncSequence<T>;
|
|
readonly #equater: MaybeAsyncEquater<T> | undefined;
|
|
|
|
constructor(first: AsyncSequence<T>, second: AsyncSequence<T>, equater?: MaybeAsyncEquater<T>) {
|
|
super();
|
|
|
|
this.#first = first;
|
|
this.#second = second;
|
|
this.#equater = equater;
|
|
}
|
|
|
|
override async *iterator() {
|
|
const set = createAsyncEqualitySet(this.#equater);
|
|
|
|
for await (const obj of this.#second) {
|
|
await set.add(obj);
|
|
}
|
|
|
|
for await (const obj of this.#first) {
|
|
if (await set.remove(obj)) {
|
|
yield obj;
|
|
}
|
|
}
|
|
|
|
set.clear();
|
|
}
|
|
}
|
|
|
|
export class IntersectByAsyncSequence<T, U> extends BaseAsyncSequence<T> {
|
|
readonly #first: AsyncSequence<T>;
|
|
readonly #second: AsyncSequence<T>;
|
|
readonly #selector: MaybeAsyncConverter<T, U>;
|
|
readonly #equater: MaybeAsyncEquater<U> | undefined;
|
|
|
|
constructor(first: AsyncSequence<T>, second: AsyncSequence<T>, selector: MaybeAsyncConverter<T, U>, equater?: MaybeAsyncEquater<U>) {
|
|
super();
|
|
|
|
this.#first = first;
|
|
this.#second = second;
|
|
this.#selector = selector;
|
|
this.#equater = equater;
|
|
}
|
|
|
|
override async *iterator() {
|
|
const set = createAsyncEqualitySet(this.#equater);
|
|
|
|
for await (const obj of this.#second) {
|
|
await set.add(await this.#selector(obj));
|
|
}
|
|
|
|
for await (const obj of this.#first) {
|
|
if (await set.remove(await this.#selector(obj))) {
|
|
yield obj;
|
|
}
|
|
}
|
|
|
|
set.clear();
|
|
}
|
|
}
|
|
|
|
export class ReversedAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
|
|
constructor(sequence: AsyncSequence<T>) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
}
|
|
|
|
override async *iterator() {
|
|
const buffer: T[] = [];
|
|
|
|
for await (const obj of this.#sequence) {
|
|
buffer.push(obj);
|
|
}
|
|
|
|
for (let i = buffer.length - 1; i >= 0; i--) {
|
|
yield buffer[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
export class GroupByAsyncSequence<TElement, TKey, TResult> extends BaseAsyncSequence<GroupedAsyncSequence<TKey, TResult>> {
|
|
readonly #sequence: AsyncSequence<TElement>;
|
|
readonly #keySelector: MaybeAsyncConverter<TElement, TKey>;
|
|
readonly #elementSelector: MaybeAsyncConverter<TElement, TResult>;
|
|
readonly #keyComparer: MaybeAsyncEquater<TKey> | undefined;
|
|
|
|
constructor(sequence: AsyncSequence<TElement>, keySelector: MaybeAsyncConverter<TElement, TKey>, elementSelector?: MaybeAsyncConverter<TElement, TResult>, keyComparer?: MaybeAsyncEquater<TKey>) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#keySelector = keySelector;
|
|
this.#elementSelector = elementSelector ?? identity as MaybeAsyncConverter<TElement, TResult>;
|
|
this.#keyComparer = keyComparer;
|
|
}
|
|
|
|
override async *iterator() {
|
|
const groupings = createAsyncEqualityMap<TKey, TResult[]>(this.#keyComparer);
|
|
|
|
for await (const obj of this.#sequence) {
|
|
const key = await this.#keySelector(obj);
|
|
let grouping = await groupings.get(key);
|
|
|
|
if (!grouping) {
|
|
await groupings.set(key, grouping = []);
|
|
}
|
|
|
|
grouping.push(await this.#elementSelector(obj));
|
|
}
|
|
|
|
for (const entry of groupings) {
|
|
yield new GroupedAsyncSequenceImpl(entry[0], array(entry[1]));
|
|
}
|
|
}
|
|
}
|
|
|
|
export class ChunkedAsyncSequence<T> extends BaseAsyncSequence<T[]> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
readonly #size: number;
|
|
|
|
constructor(sequence: AsyncSequence<T>, size: number) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#size = size;
|
|
}
|
|
|
|
override async nonEnumeratedCount() {
|
|
const n = await this.#sequence.nonEnumeratedCount();
|
|
return n < 0 ? -1 : Math.ceil(n / this.#size);
|
|
}
|
|
|
|
override async *iterator() {
|
|
let chunk: T[] = [];
|
|
|
|
for await (const obj of this.#sequence) {
|
|
chunk.push(obj);
|
|
|
|
if (chunk.length === this.#size) {
|
|
yield chunk;
|
|
chunk = [];
|
|
}
|
|
}
|
|
|
|
if (chunk.length > 0) {
|
|
yield chunk;
|
|
}
|
|
}
|
|
}
|
|
|
|
export class JoinAsyncSequence<TOuter, TInner, TKey, TResult> extends BaseAsyncSequence<TResult> {
|
|
readonly #first: AsyncSequence<TOuter>;
|
|
readonly #second: AsyncSequence<TInner>;
|
|
readonly #firstKeySelector: MaybeAsyncConverter<TOuter, TKey>;
|
|
readonly #secondKeySelector: MaybeAsyncConverter<TInner, TKey>;
|
|
readonly #resultSelector: MaybeAsyncBiConverter<TOuter, TInner, TResult>;
|
|
readonly #keyComparer: MaybeAsyncEquater<TKey>;
|
|
|
|
constructor(first: AsyncSequence<TOuter>, second: AsyncSequence<TInner>, firstKeySelector: MaybeAsyncConverter<TOuter, TKey>, secondKeySelector: MaybeAsyncConverter<TInner, TKey>, resultSelector?: MaybeAsyncBiConverter<TOuter, TInner, TResult>, keyComparer?: MaybeAsyncEquater<TKey>) {
|
|
super();
|
|
|
|
this.#first = first;
|
|
this.#second = second;
|
|
this.#firstKeySelector = firstKeySelector;
|
|
this.#secondKeySelector = secondKeySelector;
|
|
this.#resultSelector = resultSelector ?? identity as MaybeAsyncBiConverter<TOuter, TInner, TResult>;
|
|
this.#keyComparer = keyComparer ?? strictEquals;
|
|
}
|
|
|
|
override async *iterator() {
|
|
for await (const firstObj of this.#first) {
|
|
const firstKey = await this.#firstKeySelector(firstObj);
|
|
|
|
for await (const secondObj of this.#second) {
|
|
const secondKey = await this.#secondKeySelector(secondObj);
|
|
|
|
if (await this.#keyComparer(firstKey, secondKey)) {
|
|
yield await this.#resultSelector(firstObj, secondObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export class GroupJoinAsyncSequence<TOuter, TInner, TKey, TResult> extends BaseAsyncSequence<TResult> {
|
|
readonly #first: AsyncSequence<TOuter>;
|
|
readonly #second: AsyncSequence<TInner>;
|
|
readonly #firstKeySelector: MaybeAsyncConverter<TOuter, TKey>;
|
|
readonly #secondKeySelector: MaybeAsyncConverter<TInner, TKey>;
|
|
readonly #resultSelector: MaybeAsyncBiConverter<TOuter, AsyncSequence<TInner>, TResult>;
|
|
readonly #keyComparer: MaybeAsyncEquater<TKey>;
|
|
|
|
constructor(first: AsyncSequence<TOuter>, second: AsyncSequence<TInner>, firstKeySelector: MaybeAsyncConverter<TOuter, TKey>, secondKeySelector: MaybeAsyncConverter<TInner, TKey>, resultSelector?: MaybeAsyncBiConverter<TOuter, AsyncSequence<TInner>, TResult>, keyComparer?: MaybeAsyncEquater<TKey>) {
|
|
super();
|
|
|
|
this.#first = first;
|
|
this.#second = second;
|
|
this.#firstKeySelector = firstKeySelector;
|
|
this.#secondKeySelector = secondKeySelector;
|
|
this.#resultSelector = resultSelector ?? GroupJoinAsyncSequence.#defaultResultSelector as MaybeAsyncBiConverter<TOuter, AsyncSequence<TInner>, TResult>;
|
|
this.#keyComparer = keyComparer ?? strictEquals;
|
|
}
|
|
|
|
static #defaultResultSelector<TOuter, TInner>(first: TOuter, second: AsyncSequence<TInner>) {
|
|
return new GroupedAsyncSequenceImpl(first, second);
|
|
}
|
|
|
|
override async *iterator() {
|
|
for await (const firstObj of this.#first) {
|
|
const firstKey = await this.#firstKeySelector(firstObj);
|
|
const secondObjs: TInner[] = [];
|
|
|
|
for await (const secondObj of this.#second) {
|
|
const secondKey = await this.#secondKeySelector(secondObj);
|
|
|
|
if (await this.#keyComparer(firstKey, secondKey)) {
|
|
secondObjs.push(secondObj);
|
|
}
|
|
}
|
|
|
|
// yield this.#resultSelector(firstObj, this.#second.where(secondObj => this.#keyComparer(firstKey, this.#secondKeySelector(secondObj))));
|
|
yield this.#resultSelector(firstObj, array(secondObjs));
|
|
}
|
|
}
|
|
}
|
|
|
|
export class RemoveAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
readonly #obj: T;
|
|
readonly #all: boolean;
|
|
readonly #equater: MaybeAsyncEquater<T>;
|
|
|
|
constructor(sequence: AsyncSequence<T>, obj: T, all?: boolean, equater?: MaybeAsyncEquater<T>) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
this.#obj = obj;
|
|
this.#all = all ?? false;
|
|
this.#equater = equater ?? strictEquals;
|
|
}
|
|
|
|
override async *iterator() {
|
|
let gotOne = false;
|
|
|
|
for await (const obj of this.#sequence) {
|
|
if (await this.#equater(this.#obj, obj)) {
|
|
if (this.#all) {
|
|
continue;
|
|
}
|
|
|
|
if (!gotOne) {
|
|
gotOne = true;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
yield obj;
|
|
}
|
|
}
|
|
}
|
|
|
|
export class CacheAsyncSequence<T> extends BaseAsyncSequence<T> {
|
|
readonly #sequence: AsyncSequence<T>;
|
|
#cache: T[] | undefined;
|
|
|
|
constructor(sequence: AsyncSequence<T>) {
|
|
super();
|
|
|
|
this.#sequence = sequence;
|
|
}
|
|
|
|
override async *iterator() {
|
|
yield* this.#cache ??= await this.#sequence.toArray();
|
|
}
|
|
}
|