export function* iterFromIndex( array: T[], index: number ): Generator { for (let i = index; i < array.length; i++) { yield array[i]; } } export function* iterFilter( iterator: Iterable, predicate: (value: T) => boolean ): Generator { for (const value of iterator) { if (predicate(value)) { yield value; } } } export function* iterConcat( ...iterators: Iterable[] ): Generator { for (const iterator of iterators) { for (const value of iterator) { yield value; } } } export function* iterUnique( iterator: Iterable ): Generator { const seen = new Set(); for (const value of iterator) { if (!seen.has(value)) { seen.add(value); yield value; } } } export function* iterMap( iterator: Iterable, mapper: (value: T) => U ): Generator { for (const value of iterator) { yield mapper(value); } } // Return an empty iterator export function iterEmpty() { return (function* () {})(); } // AsyncIterable export async function* asyncIterTake( iterator: AsyncIterable | Iterable, count: number ): AsyncGenerator { let i = 0; for await (const result of iterator) { if (i >= count) { return; } yield result; i++; } } export async function* asyncIterFilter( iterator: AsyncIterable | Iterable, predicate: (value: T) => boolean | Promise ): AsyncGenerator { for await (const result of iterator) { if (await predicate(result)) { yield result; } } } export async function* asyncIterConcat( ...iterators: (AsyncIterable | Iterable)[] ): AsyncGenerator { for (const iterator of iterators) { for await (const result of iterator) { yield result; } } } export async function* asyncIterUnique( iterator: AsyncIterable | Iterable, getId?: (value: T) => any ): AsyncGenerator { const seen = new Set(); for await (const result of iterator) { const id = getId ? getId(result) : result; if (!seen.has(id)) { seen.add(id); yield result; } } } export async function* asyncIterMap( iterator: AsyncIterable | Iterable, mapper: (value: T) => U ): AsyncGenerator { for await (const item of iterator) { yield mapper(item); } } export async function asyncIterEvery( iterator: AsyncIterable | Iterable, predicate: (value: T) => boolean | Promise ): Promise { // TODO: look into using sync iterator when possible for await (const item of iterator) { if (!(await predicate(item))) { return false; } } return true; } export async function asyncIterSome( iterator: AsyncIterable | Iterable, predicate: (value: T) => boolean | Promise ): Promise { for await (const item of iterator) { if (await predicate(item)) { return true; } } return false; }