export function* chunks(iter: Iterable, size = 100): Iterable { let buf: T[] = [] for (const item of iter) { buf.push(item) if (buf.length === size) { yield buf buf = [] } } if (buf.length) yield buf } export function zip( iter1: Iterable, iter2: Iterable ): Iterable<[T1, T2]> export function zip( iter1: Iterable, iter2: Iterable, iter3: Iterable ): Iterable<[T1, T2, T3]> export function zip(...iters: Iterable[]): Iterable export function* zip(...iters: Iterable[]): Iterable { const iterables = iters.map((iter) => iter[Symbol.iterator]()) for (;;) { const row = [] for (const iter of iterables) { const res = iter.next() if (res.done) return row.push(res.value) } yield row } } export async function groupByAsync( items: Iterable, keyer: (item: T) => Promise ): Promise> { const ret: Record = {} as any for (const item of items) { const key = await keyer(item) if (!ret[key]) ret[key] = [] ret[key].push(item) } return ret }