export function includesSequence<T>(left: Queryable<T>, right: Queryable<T>, equaler: EqualityComparison<T> | Equaler<T> = Equaler.defaultEqualer): boolean { if (typeof equaler === "function") equaler = Equaler.create(equaler); assert.mustBeQueryable(left, "source"); assert.mustBeQueryable(right, "other"); assert.mustBeEqualer(equaler, "equaler"); const rightArray = toArray(right); const numRightElements = rightArray.length; if (numRightElements <= 0) { return true; } const span: T[] = []; for (const leftValue of ToIterable(left)) { for (;;) { const rightValue = rightArray[span.length]; if (equaler.equals(leftValue, rightValue)) { if (span.length + 1 >= numRightElements) { return true; } span.push(leftValue); } else if (span.length > 0) { span.shift(); continue; } break; } } return false; }
export async function correspondsByAsync<T, K>(left: AsyncQueryable<T>, right: AsyncQueryable<T>, leftKeySelector: (element: T) => K, rightKeySelector: (element: T) => K = leftKeySelector, keyEqualer: EqualityComparison<K> | Equaler<K> = Equaler.defaultEqualer): Promise<boolean> { assert.mustBeAsyncQueryable<T>(left, "left"); assert.mustBeAsyncQueryable<T>(right, "right"); assert.mustBeFunction(leftKeySelector, "leftKeySelector"); assert.mustBeFunction(rightKeySelector, "rightKeySelector"); assert.mustBeObject(keyEqualer, "keyEqualer"); if (typeof keyEqualer === "function") keyEqualer = Equaler.create(keyEqualer); const leftIterator = GetAsyncIterator(ToPossiblyAsyncIterable(left)); let leftDone = false; let leftValue: T; try { const rightIterator = GetAsyncIterator(ToPossiblyAsyncIterable(right)); let rightDone = false; let rightValue: T; try { for (;;) { ({ done: leftDone, value: leftValue } = await leftIterator.next()); ({ done: rightDone, value: rightValue } = await rightIterator.next()); if (leftDone && rightDone) return true; if (Boolean(leftDone) !== Boolean(rightDone) || !keyEqualer.equals(leftKeySelector(leftValue), rightKeySelector(rightValue))) return false; } } finally { if (!rightDone) await AsyncIteratorClose(rightIterator); } } finally { if (!leftDone) await AsyncIteratorClose(leftIterator); } }
export async function startsWithAsync<T>(left: AsyncQueryable<T>, right: AsyncQueryable<T>, equaler: EqualityComparison<T> | Equaler<T> = Equaler.defaultEqualer): Promise<boolean> { if (typeof equaler === "function") equaler = Equaler.create(equaler); assert.mustBeAsyncQueryable<T>(left, "left"); assert.mustBeAsyncQueryable<T>(right, "right"); assert.mustBeEqualer(equaler, "equaler"); const leftIterator = GetAsyncIterator(ToPossiblyAsyncIterable(left)); let leftDone = false; let leftValue: T; try { const rightIterator = GetAsyncIterator(ToPossiblyAsyncIterable(right)); let rightDone = false; let rightValue: T; try { for (;;) { ({ done: leftDone, value: leftValue } = await leftIterator.next()); ({ done: rightDone, value: rightValue } = await rightIterator.next()); if (rightDone) return true; if (leftDone || !equaler.equals(leftValue, rightValue)) return false; } } finally { if (!rightDone) await AsyncIteratorClose(rightIterator); } } finally { if (!leftDone) await AsyncIteratorClose(leftIterator); } }
export function includes<T>(source: Queryable<T>, value: T, equaler: EqualityComparison<T> | Equaler<T> = Equaler.defaultEqualer): boolean { if (typeof equaler === "function") equaler = Equaler.create(equaler); assert.mustBeQueryable(source, "source"); assert.mustBeEqualer(equaler, "equaler"); for (const element of ToIterable(source)) { if (equaler.equals(value, element)) { return true; } } return false; }
export async function includesAsync<T>(source: AsyncQueryable<T>, value: T, equaler: EqualityComparison<T> | Equaler<T> = Equaler.defaultEqualer): Promise<boolean> { if (typeof equaler === "function") equaler = Equaler.create(equaler); assert.mustBeAsyncQueryable<T>(source, "source"); assert.mustBeEqualer(equaler, "equaler"); for await (const element of ToPossiblyAsyncIterable(source)) { if (equaler.equals(value, element)) { return true; } } return false; }
export function toSet<T>(source: Queryable<T>, elementSelector: ((element: T) => T) | Equaler<T> = identity, equaler?: Equaler<T>): Set<T> | HashSet<T> { if (IsEqualer(elementSelector)) { equaler = elementSelector; elementSelector = identity; } assert.mustBeQueryable(source, "source"); assert.mustBeFunction(elementSelector, "elementSelector"); assert.mustBeEqualerOrUndefined(equaler, "equaler"); const set = equaler ? new HashSet<T>(equaler) : new Set<T>(); for (const item of ToIterable(source)) { const element = elementSelector(item); set.add(element); } return set; }
export async function toSetAsync<T>(source: AsyncQueryable<T>, elementSelector: ((element: T) => T | PromiseLike<T>) | Equaler<T> = identity, equaler?: Equaler<T>): Promise<Set<T> | HashSet<T>> { if (IsEqualer(elementSelector)) { equaler = elementSelector; elementSelector = identity; } assert.mustBeAsyncQueryable<T>(source, "source"); assert.mustBeFunction(elementSelector, "elementSelector"); assert.mustBeEqualerOrUndefined(equaler, "equaler"); const set = equaler ? new HashSet<T>(equaler) : new Set<T>(); for await (const item of ToPossiblyAsyncIterable(source)) { const element = await elementSelector(item); set.add(element); } return set; }
export function toMap<T, K>(source: Queryable<T>, keySelector: (element: T) => K, elementSelector: ((element: T) => T) | Equaler<K> = identity, keyEqualer?: Equaler<K>): Map<K, T> | HashMap<K, T> { if (IsEqualer(elementSelector)) { keyEqualer = elementSelector; elementSelector = identity; } assert.mustBeQueryable(source, "source"); assert.mustBeFunction(keySelector, "keySelector"); assert.mustBeFunction(elementSelector, "elementSelector"); assert.mustBeEqualerOrUndefined(keyEqualer, "keyEqualer"); const map = keyEqualer ? new HashMap<K, T>(keyEqualer) : new Map<K, T>(); for (const item of ToIterable(source)) { const key = keySelector(item); const element = elementSelector(item); map.set(key, element); } return map; }
export async function toMapAsync<T, K>(source: AsyncQueryable<T>, keySelector: (element: T) => K, elementSelector: ((element: T) => T | PromiseLike<T>) | Equaler<K> = identity, keyEqualer?: Equaler<K>): Promise<Map<K, T> | HashMap<K, T>> { if (IsEqualer(elementSelector)) { keyEqualer = elementSelector; elementSelector = identity; } assert.mustBeAsyncQueryable<T>(source, "source"); assert.mustBeFunction(keySelector, "keySelector"); assert.mustBeFunction(elementSelector, "elementSelector"); assert.mustBeEqualerOrUndefined(keyEqualer, "keyEqualer"); const map = keyEqualer ? new HashMap<K, T>(keyEqualer) : new Map<K, T>(); for await (const item of ToPossiblyAsyncIterable(source)) { const key = keySelector(item); const element = await elementSelector(item); map.set(key, element); } return map; }
export async function endsWithAsync<T>(left: AsyncQueryable<T>, right: AsyncQueryable<T>, equaler: EqualityComparison<T> | Equaler<T> = Equaler.defaultEqualer): Promise<boolean> { if (typeof equaler === "function") equaler = Equaler.create(equaler); assert.mustBeAsyncQueryable<T>(left, "left"); assert.mustBeAsyncQueryable<T>(right, "right"); assert.mustBeEqualer(equaler, "equaler"); const rightArray = await toArrayAsync(right); const numElements = rightArray.length; if (numElements <= 0) { return true; } const leftArray = await toArrayAsync(takeRightAsync(left, numElements)); if (leftArray.length < numElements) { return false; } for (let i = 0; i < numElements; i++) { if (!equaler.equals(leftArray[i], rightArray[i])) { return false; } } return true; }