1
0

add cartesian product

This commit is contained in:
Herve BECHER
2025-10-19 14:41:58 +02:00
parent 1fb91deabd
commit 5852319315
4 changed files with 98 additions and 0 deletions

View File

@@ -664,6 +664,10 @@ export abstract class BaseAsyncSequence<TElement> extends AsyncSequenceMarker im
return new ZippedAsyncSequence<TElement, TOther>(this, wrap(sequence)); return new ZippedAsyncSequence<TElement, TOther>(this, wrap(sequence));
} }
cartesianProduct<TOther>(sequence: MaybeAsyncIterable<TOther>): AsyncSequence<[TElement, TOther]> {
return new CartesianProductAsyncSequence<TElement, TOther>(this, wrap(sequence));
}
indexed(): AsyncSequence<[number, TElement]> { indexed(): AsyncSequence<[number, TElement]> {
return new IndexedAsyncSequence<TElement>(this); return new IndexedAsyncSequence<TElement>(this);
} }
@@ -1022,6 +1026,10 @@ export class DelegatedAsyncSequence<TElement> extends AsyncSequenceMarker implem
return this.#sequence.zip(wrap(sequence)); return this.#sequence.zip(wrap(sequence));
} }
cartesianProduct<TOther>(sequence: MaybeAsyncIterable<TOther>): AsyncSequence<[TElement, TOther]> {
return this.#sequence.cartesianProduct(wrap(sequence));
}
indexed(): AsyncSequence<[number, TElement]> { indexed(): AsyncSequence<[number, TElement]> {
return this.#sequence.indexed(); return this.#sequence.indexed();
} }
@@ -1821,6 +1829,46 @@ class ZippedAsyncSequence<T, U> extends BaseAsyncSequence<[T, U]> {
} }
} }
export class CartesianProductAsyncSequence<T, U> extends BaseAsyncSequence<[T, 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 n1 = await this.#first.nonEnumeratedCount();
if (n1 < 0) {
return -1;
}
const n2 = await this.#second.nonEnumeratedCount();
if (n2 < 0) {
return -1;
}
return n1 * n2;
}
override async maxCount() {
return await this.#first.maxCount() * await this.#second.maxCount();
}
override async *iterator() {
for await (const firstObj of this.#first) {
for await (const secondObj of this.#second) {
yield [firstObj, secondObj] as [T, U];
}
}
}
}
class UnionAsyncSequence<T> extends BaseAsyncSequence<T> { class UnionAsyncSequence<T> extends BaseAsyncSequence<T> {
readonly #first: AsyncSequence<T>; readonly #first: AsyncSequence<T>;
readonly #second: AsyncSequence<T>; readonly #second: AsyncSequence<T>;

View File

@@ -108,6 +108,7 @@ export interface AsyncSequence<TElement> extends AsyncIterable<TElement> {
forEach(action: MaybeAsyncAction<TElement>): Promise<void>; forEach(action: MaybeAsyncAction<TElement>): Promise<void>;
zip<TOther>(sequence: MaybeAsyncIterable<TOther>): AsyncSequence<[TElement, TOther]>; zip<TOther>(sequence: MaybeAsyncIterable<TOther>): AsyncSequence<[TElement, TOther]>;
cartesianProduct<TOther>(sequence: MaybeAsyncIterable<TOther>): AsyncSequence<[TElement, TOther]>;
indexed(): AsyncSequence<[number, TElement]>; indexed(): AsyncSequence<[number, TElement]>;

View File

@@ -673,6 +673,10 @@ export abstract class BaseSequence<TElement> extends SequenceMarker implements S
return new ZippedSequence<TElement, TOther>(this, wrap(sequence)); return new ZippedSequence<TElement, TOther>(this, wrap(sequence));
} }
cartesianProduct<TOther>(sequence: Iterable<TOther>): Sequence<[TElement, TOther]> {
return new CartesianProductSequence<TElement, TOther>(this, wrap(sequence));
}
indexed(): Sequence<[number, TElement]> { indexed(): Sequence<[number, TElement]> {
return new IndexedSequence<TElement>(this); return new IndexedSequence<TElement>(this);
} }
@@ -1039,6 +1043,10 @@ export class DelegatedSequence<TElement> extends SequenceMarker implements Seque
return this.#sequence.zip(sequence); return this.#sequence.zip(sequence);
} }
cartesianProduct<TOther>(sequence: Iterable<TOther>) {
return this.#sequence.cartesianProduct(sequence);
}
indexed() { indexed() {
return this.#sequence.indexed(); return this.#sequence.indexed();
} }
@@ -2094,6 +2102,46 @@ export class ZippedSequence<T, U> extends BaseSequence<[T, U]> {
} }
} }
export class CartesianProductSequence<T, U> extends BaseSequence<[T, U]> {
readonly #first: Sequence<T>;
readonly #second: Sequence<U>;
constructor(first: Sequence<T>, second: Sequence<U>) {
super();
this.#first = first;
this.#second = second;
}
override nonEnumeratedCount() {
const n1 = this.#first.nonEnumeratedCount();
if (n1 < 0) {
return -1;
}
const n2 = this.#second.nonEnumeratedCount();
if (n2 < 0) {
return -1;
}
return n1 * n2;
}
override maxCount() {
return this.#first.maxCount() * this.#second.maxCount();
}
override *iterator() {
for (const firstObj of this.#first) {
for (const secondObj of this.#second) {
yield [firstObj, secondObj] as [T, U];
}
}
}
}
class UnionSequence<T> extends BaseSequence<T> { class UnionSequence<T> extends BaseSequence<T> {
readonly #first: Sequence<T>; readonly #first: Sequence<T>;
readonly #second: Sequence<T>; readonly #second: Sequence<T>;

View File

@@ -111,6 +111,7 @@ export interface Sequence<TElement> extends Iterable<TElement> {
forEach(action: Action<TElement>): void; forEach(action: Action<TElement>): void;
zip<TOther>(sequence: Iterable<TOther>): Sequence<[TElement, TOther]>; zip<TOther>(sequence: Iterable<TOther>): Sequence<[TElement, TOther]>;
cartesianProduct<TOther>(sequence: Iterable<TOther>): Sequence<[TElement, TOther]>;
indexed(): Sequence<[number, TElement]>; indexed(): Sequence<[number, TElement]>;